This is a follow up question of an answer to Jackson custom getters.
The solution works and creates proper JSON. The problem is deserialization. I have an unwrapped object with some attributes not shown in JSON but instead replaced by a new attribute (e.g. firstname+surname => name).
This is correctly serialized to
{"age":22,"name":"Alex Doe"}
This class can not be edited, so we rely on mixin.
The problem on deserialization is, that PersonSerializer.setFullname()
is called before PersonSerializer.setPerson()
, probably because attributes are deserialized before subobjects. Which forces me to have a Person
-object created when PersonSerializer
is created by the ObjectMapper
. This Person
-object is overwritten when age is deserialized with an Person
-object only containing the age:
firstName: null, surname: null, age: 22
I could store fullname
in setFullname()
and fill it into person
when setPerson()
is called but this feels incorrect.
What is the proper way to solve this problem?
Code:
public final class Person {
private String firstName;
private String surname;
private int age;
public Person() {
super();
}
Person(final String firstName, final String surname, final int age) {
super();
this.firstName = firstName;
this.surname = surname;
this.age = age;
}
//getter and setter
}
Serialization helper and mixin based on the answer:
public class PersonSerializer {
private Person person;
public PersonSerializer() {
super();
person = new Person(); //needed, otherwise NPE in setFullname()
}
@JsonUnwrapped
Person getPerson() {
return person;
}
//customer getter to join firstname and surname
@JsonGetter("name")
String fullName() {
return person.getFirstName() + " " + person.getSurname();
}
@JsonSetter("name")
public void setFullname(final String fullName) {
final String[] s = fullName.split(" ");
person.setFirstName(s[0]);
person.setSurname(s[1]);
}
public void setPerson(Person p) {
person = p;
}
}
and
abstract class PersonMixin {
@JsonIgnore String firstName;
@JsonIgnore String surname;
}
Testcode:
public static void main(String[] args)
throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper().addMixIn(Person.class, PersonMixin.class);
mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
final PersonSerializer alex = new PersonSerializer();
alex.setPerson(new Person("Alex", "Doe", 22));
final String s = mapper.writeValueAsString(alex);
out.println(s);
final Person newAlex = mapper.readValue(s, PersonSerializer.class).getPerson();
out.println(String.format(
"firstName: %s, surname: %s, age: %d",
newAlex.getFirstName(),
newAlex.getSurname(),
newAlex.getAge()
));
}
I searched for examples, documentation and StackOverflow but to no avail.
2
Answers
You can try this solution, it works fine:
You only need the person calss to get that you want
OUTPUT is :
Let me know
I think your code can be more simple:
What you need is a Wrapper of Person class since you can’t edit it.
Person:
Person Wrapper
PersonMixIn:
TEST:
result:
Serialization: {"age":22,"name":"Alex Doe"}
Deserialization: firstName: Alex, surname: Doe, age: 22