Search code examples
javajsonjacksondeserialization

Java Generics not working with Jackson Serlializer


I have a class representing a generic API response:

@Setter
@Getter
public final class ApiResponse<T> {
    private T data;
}

I set the data with the help of Jackson like below:

class Converter<T> {
  ApiResponse<T> create(){
     // some REST calls and form httpResponse before this step
     ApiResponse<T> apiResponse = new ApiResponse();
     T data = objectMapper
         .readValue(httpResponse.body(), new TypeReference<>() {});
     apiResponse.setData(data);
     return apiResponse;
  }
}

Then I tried to use it with a custom object, as shown below:

Converter<MyObject> converter = new Converter<>();
ApiResponse<MyObject> apiResponse = converter.create();

But I observe that apiResponse.getData() always return LinkedHashMap instead of Myobject type.

Here is MyObject class:

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public final class MyObject {
  @JsonProperty("childs")
  private ChildObject[] childs;
}

What am I doing wrong here?

here is the http response body for reference:

{
  "childs": [
    {
      "freightLineId": "",
      "shipmentId": "",
      "shipmentVersionId": ""
    }
  ]
}

Solution

  • You can try generic method instead of generic class and pass the class type as parameter inside the method

    Converter.java

    public class Converter {
        public static ObjectMapper objectMapper = new ObjectMapper();
        public static <T> T create(String json, Class<T> classType) throws Exception {
            return (T) objectMapper.readValue(json, classType);
        }
    }
    

    main code

    MyObject obj = Converter.create("{\n"
                        + "  \"childs\": [\n"
                        + "    {\n"
                        + "      \"freightLineId\": \"0001\",\n"
                        + "      \"shipmentId\": \"1000\",\n"
                        + "      \"shipmentVersionId\": \"1.0\"\n"
                        + "    }\n"
                        + "  ]\n"
                        + "}", MyObject.class);
                
    System.out.println(obj.getChilds());
    

    Code for ApiResponse<T>

    public class Converter {
        public static ObjectMapper objectMapper = new ObjectMapper();
        public static <T> ApiResponse<T> create(String json, Class<T> classType) throws Exception {
            ApiResponse<T> res = new ApiResponse<>();
            res.setData((T) objectMapper.readValue(json, classType));
            return res;
        }
    }
    

    main code

    ApiResponse<MyObject> obj = Converter.create("{\n"
                        + "  \"childs\": [\n"
                        + "    {\n"
                        + "      \"freightLineId\": \"0001\",\n"
                        + "      \"shipmentId\": \"1000\",\n"
                        + "      \"shipmentVersionId\": \"1.0\"\n"
                        + "    }\n"
                        + "  ]\n"
                        + "}", MyObject.class);
    System.out.println( obj.getData().getChilds() );