Jackson JSON库:如何实例化包含抽象字段的类

时间:2011-03-30 16:58:55

标签: java json jackson deserialization

我想将JSON字符串转换为java对象,但此对象的类包含抽象字段,Jackson无法实例化,也不会生成对象。告诉它关于抽象类的一些默认实现的最简单方法是什么,比如

setDefault(AbstractAnimal.class, Cat.class);

或者根据JSON属性名称来决定实现类,例如。对于JSON对象:

{
    ...
    cat: {...}
    ...
}

我愿意:

setImpl("cat", Cat.class);


我知道Jackson可以在JSON中嵌入类信息,但我不想让我使用的JSON格式复杂化。我想通过设置默认实现类或属性名称('cat')来决定使用哪个类 - 就像在XStream库中一样,你写的是:

xStream.alias("cat", Cat.class);

有没有办法这样做,特别是在一行中,还是需要更多的代码?

4 个答案:

答案 0 :(得分:39)

有多种方式;在版本1.8之前,最简单的方法可能是:

@JsonDeserialize(as=Cat.class)
public abstract class AbstractAnimal { ... }

关于基于属性的决定,最好使用@JsonTypeInfo来完成,它会自动嵌入(写入时)和使用类型信息。

有多种类型的信息(类名,逻辑类型名称),以及包含机制(as-included-property,as-wrapper-array,as-wrapper-object)。本页:https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization解释了一些概念。

答案 1 :(得分:2)

这里有一个非常明确的例子的完整答案:https://stackoverflow.com/a/30386694/584947

杰克逊将此称为多态反序列化。

这对我的问题肯定有帮助。我有一个抽象类,我在数据库中保存,需要将它解组为一个类的具体实例(可以理解)。

它将向您展示如何正确地注释父抽象类以及如何教授jackson如何在解组时在运行时选择可用的子类候选者。

答案 2 :(得分:0)

问题可以通过抽象类上的@JsonDeserialize注释解决 指杰克逊异常问题和解决方案 https://www.baeldung.com/jackson-exception

答案 3 :(得分:0)

如果您既不想使用额外的字段来污染JSON,也不希望使用批注来污染您的类,则可以编写一个非常简单的模块和反序列化器,该模块和反序列化器使用您想要的默认子类。由于有一些样板代码,它不止一行,但是它仍然相对简单。

class AnimalDeserializer extends StdDeserializer<Animal> {
    public AnimalDeserializer() {
        super(Animal.class);
    }

    public Animal deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
        return jsonParser.readValueAs(Cat.class);
    }
}

class AnimalModule extends SimpleModule {
    {
        addDeserializer(Animal.class, new AnimalDeserializer());
    }
}

然后为ObjectMapper注册该模块,就是这样(Zoo是具有Animal字段的容器类)。

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new AnimalModule());
return objectMapper.readValue(json, Zoo.class);