question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Deserialization Not Working Right with Generic Types and Builders

See original GitHub issue

When trying to deserialize a generic type using a builder it is deserializing the generic type as a LinkedHashMap instead of the proper type, exact same code deserialized using @JsonCreator works fine. There seems to be something missing in the builder code. Test case below demonstrates the problem:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import org.junit.Test;

import java.util.List;

public class JacksonDeserTest {
  public static class MyPOJO {
    public String x;
    public String y;

    @JsonCreator
    public MyPOJO(@JsonProperty("x") String x, @JsonProperty("y") String y) {
      this.x = x;
      this.y = y;
    }
  }

  @JsonDeserialize(builder = MyGenericPOJO.Builder.class)
  public static class MyGenericPOJO<T> {
    private List<T> data;

    private MyGenericPOJO(List<T> data) {
      this.data = data;
    }

    public List<T> getData() {
      return data;
    }

    public static class Builder<T> {
      private List<T> data;

      public Builder<T> withData(List<T> data) {
        this.data = data;
        return this;
      }

      public MyGenericPOJO<T> build() {
        return new MyGenericPOJO<T>(data);
      }
    }
  }

  public static class MyGenericPOJOWithCreator<T> {
    private List<T> data;

    private MyGenericPOJOWithCreator(List<T> data) {
      this.data = data;
    }

    @JsonCreator
    public static <T> MyGenericPOJOWithCreator<T> create(@JsonProperty("data") List<T> data) {
      return new MyGenericPOJOWithCreator.Builder<T>().withData(data).build();
    }

    public List<T> getData() {
      return data;
    }

    public static class Builder<T> {
      private List<T> data;

      public Builder<T> withData(List<T> data) {
        this.data = data;
        return this;
      }

      public MyGenericPOJOWithCreator<T> build() {
        return new MyGenericPOJOWithCreator<T>(data);
      }
    }
  }

  @Test
  public void testWithBuilder() throws Exception {
    final ObjectMapper mapper = new ObjectMapper();
    final String json = "{ \"data\": [ { \"x\": \"x\", \"y\": \"y\" } ] }";
    final MyGenericPOJO<MyPOJO> deserialized =
        mapper.readValue(json, new TypeReference<MyGenericPOJO<MyPOJO>>() {});
    assertThat(deserialized.data, hasSize(1));
    assertThat(deserialized.data.get(0), instanceOf(MyPOJO.class));

  }

  @Test
  public void testWithCreator() throws Exception {
    final ObjectMapper mapper = new ObjectMapper();
    final String json = "{ \"data\": [ { \"x\": \"x\", \"y\": \"y\" } ] }";
    final MyGenericPOJOWithCreator<MyPOJO> deserialized =
        mapper.readValue(json, new TypeReference<MyGenericPOJOWithCreator<MyPOJO>>() {});
    assertThat(deserialized.data, hasSize(1));
    assertThat(deserialized.data.get(0), instanceOf(MyPOJO.class));

  }
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:4
  • Comments:28 (17 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Jul 3, 2022

As per milestone indicated on the right side, was fixed for version 2.12.0 so yes, 2.12.x and 2.13.x should have the fix.

1reaction
vjkoskelacommented, Apr 28, 2020

It’s been a while since I’ve had a chance to write some Java. Well, I got back into it, and wasn’t long before I was using Jackson. That of course reminded that I may owe you @cowtowncoder a few things.

It looks like this was 2.9 and then 2.11. Is there anything on this issue I can do to move it forward and get it included in an upcoming release?

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to deserialize an object containing a generic type with a ...
I would like to keep my builder in order to have immutable object. I will try to create my own deserializer. – Thomas...
Read more >
How to Deserialize JSON Into Dynamic Object in C# - Code ...
Describe how to deserialize JSON into dynamic object in C# with detail explanation and examples using native and Newtonsoft library.
Read more >
Serialization and custom serializers - Orleans - Microsoft Learn
Orleans serializes data types passed in grain request and response messages as well as grain persistent state objects. As part of this framework ......
Read more >
JSON serialization - Immutables
Using the approach shown above, generated builders will have attributes annotated with @JsonProperty so deserialization will work properly.
Read more >
User Guide Genson - Fast and easy to use Java and Scala to ...
In some cases Genson may not serialize/deserialize a class the way you would like. First you should try to have a look at...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found