提问人:Anho 提问时间:11/10/2023 更新时间:11/18/2023 访问量:73
反序列化使用自定义 getter 创建的 JSON 并使用 Jackson 解包对象
Deserialize JSON created using custom getter and unwrapped object using Jackson
问:
这是 Jackson 自定义 getter 答案的后续问题。
该解决方案有效并创建正确的 JSON。问题在于反序列化。我有一个未包装的对象,其中包含一些未在 JSON 中显示的属性,而是被新属性替换(例如 firstname+surname => name)。
这被正确地序列化为
{"age":22,"name":"Alex Doe"}
这个类是不能编辑的,所以我们依赖 mixin。
反序列化的问题是,在 之前调用,可能是因为属性在子对象之前被反序列化。这迫使我在 .当使用仅包含 age 的 -object 反序列化 age 时,此 -object 将被覆盖:PersonSerializer.setFullname()
PersonSerializer.setPerson()
Person
PersonSerializer
ObjectMapper
Person
Person
firstName: null, surname: null, age: 22
我可以在调用时存储并填充它,但这感觉不正确。fullname
setFullname()
person
setPerson()
解决这个问题的正确方法是什么?
法典:
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
}
序列化助手和基于答案的 mixin:
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;
}
}
和
abstract class PersonMixin {
@JsonIgnore String firstName;
@JsonIgnore String surname;
}
测试代码:
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()
));
}
我搜索了示例、文档和 StackOverflow,但无济于事。
答:
您可以尝试此解决方案,它工作正常: 你只需要这个人就可以得到你想要的东西
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
public static void main(String[] args) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
final Person alex = new Person("Alex", "Doe", 22);
final String s = mapper.writeValueAsString(alex);
System.out.println(s);
final Person newAlex = mapper.readValue(s, Person.class);
System.out.println(String.format(
"firstName: %s, surname: %s, age: %d",
newAlex.getFirstName(),
newAlex.getSurname(),
newAlex.getAge()
));
}
}
输出为:
{"firstName":"Alex","surname":"Doe","age":22}
firstName: Alex, surname: Doe, age: 22
让我知道
评论
{"age":22,"name":"Alex Doe"}
{"firstName":"Alex","surname":"Doe","age":22}
我认为你的代码可以更简单: 你需要的是一个 Wrapper of Person 类,因为你无法编辑它。
人:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String firstName;
private String surname;
private int age;
}
人员包装
public class PersonWrapper extends Person {
private String name;
public PersonWrapper() {
super();
}
public PersonWrapper(String firstName, String surname, int age) {
super(firstName, surname, age);
name = getName();
}
public String getName() {
this.name = getFirstName() + " " + getSurname();
return name;
}
public void setName(final String name) {
final String[] s = name.split(" ");
setFirstName(s[0]);
setSurname(s[1]);
}
}
PersonMixIn:
public abstract class PersonMixIn {
@JsonIgnore
String firstName;
@JsonIgnore
String surname;
}
测试:
public class Application {
public static void main(String[] args) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper().addMixIn(PersonWrapper.class, PersonMixIn.class);
final PersonWrapper alex = new PersonWrapper("Alex", "Doe", 22);
final String s = mapper.writeValueAsString(alex);
System.out.println(s);
final Person newAlex = mapper.readValue(s, PersonWrapper.class);
System.out.println(String.format(
"firstName: %s, surname: %s, age: %d",
newAlex.getFirstName(),
newAlex.getSurname(),
newAlex.getAge()
));
}
}
结果:
序列化: {“age”:22,“name”:“Alex Doe”}
反序列化:名字:Alex,姓氏:Doe,年龄:22
评论
Person
评论