Jackson 将额外字段反序列化为 Map

Posted

技术标签:

【中文标题】Jackson 将额外字段反序列化为 Map【英文标题】:Jackson deserialize extra fields as Map 【发布时间】:2017-01-02 12:51:42 【问题描述】:

我希望将 JSON 对象中的任何未知字段反序列化为 Map 中的条目,它是 POJO 的成员。

例如,这里是 JSON:


  "knownField" : 5,
  "unknownField1" : "926f7c2f-1ae2-426b-9f36-4ba042334b68",
  "unknownField2" : "ed51e59d-a551-4cdc-be69-7d337162b691"

这里是 POJO:

class MyObject 
  int knownField;
  Map<String, UUID> unknownFields;
  // getters/setters whatever

有没有办法用 Jackson 来配置它?如果没有,是否有一种有效的方法来编写 StdDeserializer 来做到这一点(假设 unknownFields 中的值可以是更复杂但众所周知的一致类型)?

【问题讨论】:

【参考方案1】:

有一个特性和一个注释完全符合这个目的。

我进行了测试,它适用于您的示例中的 UUID:

class MyUUIDClass 
    public int knownField;

    Map<String, UUID> unknownFields = new HashMap<>();

    // Capture all other fields that Jackson do not match other members
    @JsonAnyGetter
    public Map<String, UUID> otherFields() 
        return unknownFields;
    

    @JsonAnySetter
    public void setOtherField(String name, UUID value) 
        unknownFields.put(name, value);
    

它会像这样工作:

    MyUUIDClass deserialized = objectMapper.readValue("" +
            "\"knownField\": 1," +
            "\"foo\": \"9cfc64e0-9fed-492e-a7a1-ed2350debd95\"" +
            "", MyUUIDClass.class);

字符串等更常见的类型也可以工作:

class MyClass 
    public int knownField;

    Map<String, String> unknownFields = new HashMap<>();

    // Capture all other fields that Jackson do not match other members
    @JsonAnyGetter
    public Map<String, String> otherFields() 
        return unknownFields;
    

    @JsonAnySetter
    public void setOtherField(String name, String value) 
        unknownFields.put(name, value);
    

(I found this feature in this blog post first).

【讨论】:

以上是关于Jackson 将额外字段反序列化为 Map的主要内容,如果未能解决你的问题,请参考以下文章

Jackson 使用枚举键、POJO 值反序列化为 Map

Jackson 将日期字符串反序列化为 Long

Jackson xml反序列化 - 序列化为一个列表,其中包含任意元素

Java Jackson将空字段反序列化为POJO中的默认空列表

将毫秒时间戳反序列化为 java.time.Instant

Jackson 反序列化同名的 xml 字段