杰克逊反序列化多态类型

3

我有以下示例类:

class Zoo {
    public Collection<? extends Animal> animals;
}

在序列化时,我尝试通过以下方式尽可能地将类型信息序列化:
  mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

我得到了以下的JSON:

[
    "com.bp.samples.json.generics.Zoo",
    {
        "animals": [
            "java.util.ArrayList",
            [
                [
                    "com.bp.samples.json.generics.Bird",
                    {
                        "name": "bird-1",
                        "wingSpan": "6 feets",
                        "preferredFood": "food-1"
                    }
                ],
                [
                    "com.bp.samples.json.generics.Cat",
                    {
                        "name": "cat-1",
                        "favoriteToy": "toy-1"
                    }
                ],
                [
                    "com.bp.samples.json.generics.Dog",
                    {
                        "name": "dog-1",
                        "breed": "bread-1",
                        "leashColor": "black"
                    }
                ]
            ]
        ]
    }
]

在反序列化方面,尝试执行以下操作:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), Zoo.class);

会导致以下异常:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: 
Can not deserialize instance of com.bp.samples.json.generics.Zoo out of START_ARRAY toke

并尝试做以下事情:

mapper.readValue(new File("./DataFiles/Zoo-2.json"), 
   new TypeReference<Collection<? extends Animal>>() {});

结果是:

Can not construct instance of com.bp.samples.json.generics.Animal, 
problem: abstract types either need to be mapped to concrete types, have custom 
deserializer, or be instantiated with additional type information
at [Source: ./DataFiles/Zoo-2.json; line: 2, column: 5]

编写自定义反序列化程序可以解决问题,但有没有一种方法可以在没有自定义反序列化程序的情况下进行反序列化呢?

谢谢, Behzad


将JSON数组(集合)反序列化为Java对象(Zoo - 不是集合)不起作用(没有特殊处理)。您必须使用DefaultTyping来提供类型信息吗?您可能需要查看http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html上的完整多态反序列化示例。 - Programmer Bruce
我建议您选择一个标签,用Java替换它(以便更引人注目地提出问题)。 - Paul Bellora
@程序员布鲁斯 我认为这里的数组是由于默认类型信息的包含,所以应该没问题。 - StaxMan
2个回答

2

就我所见,您的第一次尝试应该是有效的。我能想到的唯一解释是您正在尝试使用配置不同的ObjectMapper进行反序列化:两者都必须以相同的方式启用默认类型(因为这就是控制是否包含类型信息的内容)。

如果您正在使用相同的映射器实例(或已经配置相同),您可能需要提交错误报告,以便问题得到诊断和修复。


谢谢大家的回答。我只是认为在反序列化时,它应该查看类型信息并在不需要启用它的情况下使用它。所以,无论如何,在反序列化时我漏掉了:"mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)"。谢谢。 - Behzad Pirvali
不,没有可靠的方法来确定任意JSON对象或数组是否表示Java对象或类型信息包装器--由于歧义,设置必须匹配。 - StaxMan

1

请确保您启用了类型信息,以便反序列化使用的ObjectMapper实例。您想要反序列化为Zoo而不是动物集合,因此第一个代码片段是正确的。

您可能还想尝试 Genson lib。 我刚刚使用它检查了您的示例,一切似乎都正常。 要在Genson中启用多态类型支持,您需要配置genson实例:

Genson genson = new Genson.Builder().setWithClassMetadata(true).create();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接