I have this example class:
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class ExampleClass implements Serializable {
private String name;
private String color;
}
This class serializes to:
{
"ExampleClass":{
"name":"This is some name",
"color":"This is some color"
}}
Which is the expected behavior and I shouldn't change it. But I am receiving the file first as this json:
{
"name":"This is some name",
"color":"This is some color"
}
And I need to map it to my ExampleClass, which usually you would do as simply as:
ExampleClass example = new ObjectMapper().readValue(jsonFile, ExampleClass.class);
But since I have specified the class with annotation @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) it is trying to map the "name" field from the received json to "ExampleClass" and it throws an error:
Could not resolve type id 'name' as a subtype of
com.example.package.dto.ExampleClass
: known type ids = [ExampleClass]
I know the deserialization will work if I remove @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) or I change it to use = JsonTypeInfo.Id.NONE, but then the serialized json ends up changing so I can't do that.
I also know that if I want to add a custom deserializer I will also need to add a custom serializer, since @JsonTypeInfo annotation makes jackson ignore any deserializer you have specified in the annotation. But I really would want to avoid this case as the actual class has a lot of fields and the custom mapping classes will look very ugly.
How can I tell jackson to skip the "ExampleClass" field and to map it to it's inner fields, or specify different?
I am using fasterxml.jackson, no codehaus.
Funny enough as I was writing down my question I came up with the solution, just had to implement it and try it out and it ended up working perfectly!
Here is how I did it:
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
// no more @JsonTypeInfo here
public class ExampleClass implements Serializable {
private String name;
private String color;
}
I removed the @JsonTypeInfo from ExampleClass as this class will be used for deserializing the received json to it. Then I created this second "wrapper" class that I will be using for serializing the data:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class ExampleClassWrapper extends ExampleClass {
public ExampleClassWrapper(ExampleClass ex) {
super(ex.getName(), ex.getColor());
}
Now when the json comes I can read it in one line with no erros:
ExampleClass example = new ObjectMapper().readValue(jsonFile, ExampleClass.class);
And when I need to serialize this data (for example to send it as a request) I just send the ExampleClassWrapper:
ExampleClassWrapper wrapper = new ExampleClassWrapper(example);
exampleRestService.sendExampleRequest(wrapper);
Feel free to correct me if you think there is a better way to solve this.
P.S. HURRAY for the debugging duck that is writing questions in stackoverflow