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

问题描述

我在写标题时遇到了麻烦,因此,如果我的问题应该重新措词,我很乐意重新发布该问题以进行澄清。 :)

问题:我有这个JSON结构


  useEffect(() => {
    const getLink = async () => {
      const link = await Linking.getinitialURL();
      console.log('getLink: ',link)
    }
    getLink();
  },[]);

  useEffect(() => {
    Linking.addEventListener('url',handleDynamicLink);
    return () => {
      Linking.removeEventListener('url',handleDynamicLink);
    };
  },[]);

  const handleDynamicLink = (link: any) => {
    console.log('handleLink: ',link)
  };

  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <ScrollView
          contentInsetAdjustmentBehavior="automatic"
          style={styles.scrollView}>
            <Button
            onPress={() => {BackHandler.exitApp()}}
            title="TestButton"/>
        </ScrollView>
      </SafeAreaView>
    </>
  );
};

{if (document.getElementById('app') != null) { new Vue({ router,store,data () { return { errors: [],django_context: CONTEXT } },created() { this.$store.dispatch('products/getProducts'); },render: h => h(App),}).$mount("#app"); } 是我们要提取{ "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

当我将其序列化回JSON时,应该期望像这样:

evaluation.stats

从技术上讲,我可以将整个public class Person { String name; Map<String,Object> attributes; List<Stat> stats; } public class Stat { LocalDate date; int score; } 类映射到其自己的自定义反序列化器,但是我想尽可能地利用内置的Jackson解串器和注释。还必须将{ "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中也不应存在stats)。我在寻找一个简单且可维护的序列化/反序列化方案时遇到了麻烦。任何帮助将不胜感激!

解决方法

我不确定这是否满足您的标准,以实现简单且可维护的序列化/反序列化方案,但是您可以操纵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());

我还注释了LocalDate类中的Stat字段,如下所示:

@JsonProperty("testDate")
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd")
private LocalDate date;

非常注意:在起始JSON(问题中)中显示了以下内容:

"personality": [...],

但是在您期望的最终JSON中,您有以下内容:

"personality": {...},

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