Jackson conditional @JsonUnwrapped
Can I use @JsonUnwrapped conditionally? I don't want to use it during serialization but would like to use it while deserializing the object.
One way to do it is create two different classes or create a subclass overriding just that property which needs to behave different while serializing and deserializing. This doesn't sound right. Any other alternatives or Jackson way of tackling the problem?
Solution 1:
There is a simpler way to achieve the same result that is based on annotations only:
@JsonUnwrapped(prefix = "name_")
@JsonProperty(access = READ_ONLY)
private Name nameObject;
// method will deserialize original JSON and set it to unwrapped field
@JsonSetter
public void setName(Name name) {
this.nameObject = name;
}
// simple getter
@JsonIgnore
public Name getName() {
return this.nameObject;
}
Solution 2:
You can use MixIn feature. Using this feature POJO
class is decoupled from Jackson
annotations. You can add necessary annotation in runtime using MixIn
. See below example:
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTest {
private static final String UNWRAPPED_JSON = "{\n" +
" \"age\" : 13,\n" +
" \"first\" : \"Huckleberry\",\n" +
" \"last\" : \"Finn\"\n" +
"}";
@Test
public void test() throws IOException {
System.out.println("### Serialize without unwrapped annotation ###");
ObjectMapper serializer = new ObjectMapper();
System.out.println(serializer.writerWithDefaultPrettyPrinter().writeValueAsString(createParent()));
System.out.println("### Deserialize with unwrapped annotation ###");
ObjectMapper deserializer = new ObjectMapper();
deserializer.addMixInAnnotations(Parent.class, ParentMixIn.class);
System.out.println(deserializer.readValue(UNWRAPPED_JSON, Parent.class));
}
private Parent createParent() {
Name name = new Name();
name.first = "Tom";
name.last = "Sawyer";
Parent parent = new Parent();
parent.setAge(12);
parent.setName(name);
return parent;
}
}
class Parent {
private int age;
private Name name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
@Override
public String toString() {
return "Parent{" +
"age=" + age +
", name=" + name +
'}';
}
}
interface ParentMixIn {
@JsonUnwrapped
Name getName();
}
class Name {
public String first, last;
@Override
public String toString() {
return "Name{" +
"first='" + first + '\'' +
", last='" + last + '\'' +
'}';
}
}
Above program prints:
### Serialize without unwrapped annotation ###
{
"age" : 12,
"name" : {
"first" : "Tom",
"last" : "Sawyer"
}
}
### Deserialize with unwrapped annotation ###
Parent{age=13, name=Name{first='Huckleberry', last='Finn'}}