问题描述
我正在尝试反序列化这样的 json:
{
//other fields
"name": "John","surname": "Doe"
}
变成这样的对象:
public class SomeClass {
//other fields
private User user;
public class User {
private String name;
private String surname;
//getters and setters
}
//getters and setters
}
我尝试使用在静态方法上注释的@JsonCreator,但它不起作用(我对@JsonCreator 不太实用)。 有没有办法实现这一点,也许使用杰克逊注释?如何填充用户字段并正确填充“SomeClass”对象的“用户”字段?
注意:我不会改变json的结构或类。
@JsonAnySetter
public void setFields(String key,String value) {
if (user == null)
user = new User();
if (key.equals("name"))
user.setName(value);
else if (key.equals("surname"))
user.setSurname(value);
}
有更好的方法吗?
解决方法
您可以为此使用 Jackson
。我已经将 Jackson 2.12.1 和 Project Lombok 用于 getter 和 setter。下面是JSON序列化和反序列化的完整代码。
您的 JSON 结构需要更改为以下内容:
{
"user":{
"name": "John","surname": "Doe"
}
}
User.java
类:
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String name;
private String surname;
}
SomeClass.Java
类:
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class SomeClass {
private User user;
}
Main.java
类:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws JsonMappingException,JsonProcessingException {
String inputJSON = "{\"user\":{\"name\":\"John\",\"surname\":\"Doe\"}}";
SomeClass myUserRead = new ObjectMapper().readValue(inputJSON,SomeClass.class);
System.out.println(myUserRead.getUser().getName());
System.out.println(myUserRead.getUser().getSurname());
String myUserWrite = new ObjectMapper().writeValueAsString(myUserRead);
System.out.println(myUserWrite);
}
,
可能的选项:Jackson 的 ObjectMapper,使用类或类型引用
直接回答
ObjectMapper mapper = new ObjectMapper(); // To do the work of serialization/deserialization
String json = "{"
+ "\"name\": \"John\",\n"
+ "\"surname\": \"Doe\"\n"
+ "}";
try {
User user = mapper.readValue(json,User.class); // Deserializing directly to a Class is this easy :)
String msg = String.format("With Class,User's Name: %s,User's Surname: %s",user.getName(),user.getSurname());
System.out.println(msg);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
整体
(使用 IntelliJ 轻松访问测试库)
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.testng.annotations.Test;
public class TestDeserialization {
private ObjectMapper mapper = new ObjectMapper(); // To do the work of serialization/deserialization
private String json = "{"
+ "\"name\": \"John\",\n"
+ "\"surname\": \"Doe\"\n"
+ "}"; // Not a good way to store JSON,but here for demonstration :)
@Test
public void testDeserializationWithClass() {
try {
User user = mapper.readValue(json,User.class); // Deserializing directly to a Class is this easy :)
String msg = String.format("With Class,user.getSurname());
System.out.println(msg);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
public void testDeserializationWithTypeReference() {
try {
/*
TypeReference can handle complexity where the simple Class argument cannot; such as if we needed a Map<String,User>:
Map<String,User> userMap = mapper.readValue(json,new TypeReference<Map<String,User>>() {});
*/
User user = mapper.readValue(json,new TypeReference<User>() {});
String msg = String.format("With TypeReference,user.getSurname());
System.out.println(msg);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
package test.example;
public class User {
private String name;
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
输出
With Class,User's Name: John,User's Surname: Doe
With TypeReference,User's Surname: Doe