我在标题的措辞上遇到了一些问题,所以如果我的问题应该重新措辞,我很乐意转发这个问题进行澄清。:(
问题:我有这个JSON结构
{
"name": "Bob",
"attributes": {
"evaluation": {
"stats": [
{
"testDate": "2020-02-04",
"score": 50
},
{
"testDate": "2020-04-01",
"score": 90
},
{
"testDate": "2020-05-10",
"score": 85
}
],
"survey": {...}
},
"interests": {...},
"personality": [...],
"someRandomUnknownField": {...}
}
}
attributes
是除了我们想要提取的evaluation.stats
的之外的任何随机数的字段。我希望能够反序列化为以下类:
public class Person {
String name;
Map<String, Object> attributes;
List<Stat> stats;
}
public class Stat {
LocalDate date;
int score;
}
当我把它序列化回JSON时,我应该期待这样的东西:
{
"name": "Bob",
"attributes" : {
"evaluation": {
"survey": {...}
},
"interests" : {...},
"personality": {...},
"someRandomUnknownField": {...}
},
"stats": [
{
"testDate": "2020-02-04",
"score": 50
},
{
"testDate": "2020-04-01",
"score": 90
},
{
"testDate": "2020-05-10",
"score": 85
}
]
}
从技术上讲,我可以将整个Person
类映射到它自己的自定义反序列化程序,但我希望尽可能利用内置的Jackson反序列化程序和注释。stats
也必须提取(即stats
不应该也存在于attributes
下(。我很难找到一个简单且可维护的序列化/反序列化方案。任何帮助都将不胜感激!
我不确定这是否符合简单和可维护的序列化/反序列化方案的标准,但您可以操作JSON树将启动的JSON转换为所需的结构:
假设我从一个包含您的初始JSON:的字符串开始
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
JsonNode root = mapper.readTree(inputJson);
// copy the "stats" node to the root of the JSON:
ArrayNode statsNode = (ArrayNode) root.path("attributes").path("evaluation").path("stats");
((ObjectNode) root).set("stats", statsNode);
// delete the original "stats" node:
ObjectNode evalNode = (ObjectNode) root.path("attributes").path("evaluation");
evalNode.remove("stats");
这现在为您提供了反序列化为Person
类所需的JSON:
Person person = mapper.treeToValue(root, Person.class);
当您序列化Person object
时,您会得到以下JSON输出:
{
"name" : "Bob",
"attributes" : {
"evaluation" : {
"survey" : { }
},
"interests" : { },
"personality" : [ ],
"someRandomUnknownField" : { }
},
"stats" : [ {
"score" : 50,
"testDate" : "2020-02-04"
}, {
"score" : 90,
"testDate" : "2020-04-01"
}, {
"score" : 85,
"testDate" : "2020-05-10"
} ]
}
需要注意的是,要使其工作,您需要java.time
模块:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.11.3</version>
</dependency>
你看到了这是如何在上面的代码中注册的:
mapper.registerModule(new JavaTimeModule());
我还注释了Stat
类中的LocalDate
字段,如下所示:
@JsonProperty("testDate")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate date;
非常小的注意事项:在您开始的JSON(在问题中(中,您显示了以下内容:
"personality": [...],
但在您预期的最终JSON中,您有以下内容:
"personality": {...},
我认为这可能是一个拼写错误,在这两种情况下,它都应该是一个数组,而不是一个对象。