Jackson Unmarshall自定义对象而不是LinkedHashMap

时间:2015-07-28 07:06:15

标签: java json jackson

我有一个Java对象结果

public class MetaData {
    private List<AttributeValue<String,Object>> properties
    private String name
    ...

    ... getters/setters ...
}

AttributeValue 类是一个通用的键值类。可能存在不同的AttributeValue嵌套。 (值) Object 将是另一个AttributeValue,依此类推。

由于遗留原因,此对象的结构无法更改。

我有我的JSON,我试图映射到这个对象。 一切顺利的常规属性。此外,列表的第一级填充了AttributeValues。

问题是对象。杰克逊不知道如何解释这种嵌套行为,只是让它成为一个LinkedHashMap。

我正在寻找一种实现自定义行为的方法来告诉Jackson,这必须是一个AttributeValue对象而不是LinkedHashMap。

这就是我目前正在转换JSON的方式:

ObjectMapper om = new ObjectMapper();
MetaData metaData = om.readValue(jsonString, new TypeReference<MetaData>(){});

这是JSON的示例。 (这是通过将现有的MetaData对象序列化为JSON获得的,我可以完全控制这种语法)。

{
    "properties":[
        {
            "attribute":"creators",
            "value":[
                {
                    "attribute":"creator",
                    "value":"user1"
                },{
                    "attribute":"creator",
                    "value":"user2"
                }
            ]
        },{
            "attribute":"type",
            "value": "question"
        }
    ],
    "name":"example"
}

(顺便说一句:我使用GSON尝试了同样的方法,但是对象是一个StringMap,问题是一样的。也欢迎使用GSON的解决方案。)

修改Using Jackson ObjectMapper with Generics to POJO instead of LinkedHashMap中有来自StaxMan的评论: &#34; LinkedHashMap仅在缺少类型信息时返回(或者如果Object.class被定义为类型)。&#34;

后者似乎是这里的问题。有没有办法可以覆盖它?

1 个答案:

答案 0 :(得分:1)

如果您可以控制序列化,请尝试在地图工具上调用enableDefaultTyping()

考虑这个例子:

Pair<Integer, Pair<Integer, Integer>> pair = new Pair<>(1, new Pair<>(1, 1));
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pair);
Pair result = mapper.readValue(str, Pair.class);

如果没有enableDefaultTyping(),我会str = {"k":1,"v":{"k":1,"v":1}}Pair反序列化为LinkedHashMap enableDefaultTyping()

但如果我mapper上的str = {"k":1,"v":["Pair",{"k":1,"v":1}]},那么Pair<Integer, Pair<...>>会完全反序列化为{{1}}。