Jackson:反序列化JSON,将深层属性提取到父类中



我在标题的措辞上遇到了一些问题,所以如果我的问题应该重新措辞,我很乐意转发这个问题进行澄清。:(

问题:我有这个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": {...},

我认为这可能是一个拼写错误,在这两种情况下,它都应该是一个数组,而不是一个对象。

相关内容

  • 没有找到相关文章