Reputation: 1394
Having a dynamic POJO like the next one:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyDynamicWrapper <T> {
@JsonProperty("header")
private CommonHeader header;
@JsonProperty("payload")
private T payload;
public MyDynamicWrapper(CommonHeader header, T payload) {
super();
this.header = header;
this.payload = payload;
}
public CommonHeader getHeader() {
return header;
}
public void setHeader(CommonHeader header) {
this.header = header;
}
public T getPayload() {
return payload;
}
public void setPayload(T payload) {
this.payload = payload;
}
}
Where T
payload could be one of the following:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyPayloadOne {
@JsonProperty("status")
private int status;
@JsonProperty("action")
private String action;
...
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyPayloadTwo {
@JsonProperty("properties")
private List<String> properties = new ArrayList<>();
...
}
What is the best way to deserialize this dynamic information with Jackson? Is it mandatory to implement a deserializer? My current configuration is not dynamic and I am using:
MyDynamicWrapper pojo = jacksonMapper.readValue(jsonMessage, MyDynamicWrapper.class);
I think this is so obvious but I do not know how to indicate the dynamic reference to Jackson.
Update
In addition to the accepted answer, I have checked that also is possible to define the jackson mapper like this:
MyDynamicWrapper<?> pojo = jacksonMapper.readValue(jsonMessage, MyDynamicWrapper.class);
This will transform the POJO to both payloads.
Upvotes: 1
Views: 922
Reputation: 1321
If you know the type parameter at compile time then you may use TypeReference
to deserialize the JSON as described in the accepted answer.
In case type parameter is not known at compile time, even then JSON can be deserialized. To achieve this you would need to put certain Jackson annotations on all the classes that can be passed as type parameter to the generic MyDynamicWrapper<T>
.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("MyPayloadOne")
public class MyPayloadOne {
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("MyPayloadTwo ")
public class MyPayloadTwo {
}
Now when you deserialize an instance of MyDynamicWrapper
created using either MyPayloadOne
or MyPayloadTwo
as parameter, Jackson will put type parameter info into JSON. This JSON can then be deserialized into generic class MyDynamicWrapper.class just as you would deserialize any other class, i.e.,
without having to specify the type parameter (MyPayloadOne
or MyPayloadTwo
).
MyDynamicWrapper<?> pojo = jacksonMapper.readValue(jsonString, MyDynamicWrapper.class);
Please refer Jackson documentation on Polymorphic Deserialization and Annotations.
Upvotes: 0
Reputation: 22234
You can (and should) pass a TypeReference to readValue
to specify the type of generic class instance you want to deserialize. E.g. when wrapping MyPayloadOne
:
TypeReference ref = new TypeReference<MyDynamicWrapper<MyPayloadOne>>(){};
MyDynamicWrapper<MyPayloadOne> pojo = jacksonMapper.readValue(jsonMessage, ref);
Upvotes: 1
Reputation: 1
Try using @JsonCreator and @JsonProperty as specified in this question. Is Jackson really unable to deserialize json into a generic type?
Jackson needs a little more help to figure out what type to deserialize, and that's what those annotations help to do.
Upvotes: 0
Reputation: 1
You will need to write a custom serializer by implementing this class. Or Deserializer
Upvotes: 0