使用 Jackson 反序列化对象列表

Posted

技术标签:

【中文标题】使用 Jackson 反序列化对象列表【英文标题】:Deserialize a list of objects with Jackson 【发布时间】:2022-01-22 22:49:52 【问题描述】:

我有一个对象列表,每个对象都有指定的字段(变量类型),所以我想我将创建一个主类(超类),其中包含共享元素(变量)和特定类型变量的两个子类. 我想将所有子类反序列化为超类的类型,以便我可以将所有这些 Json 放入相同对象的列表中。

这是我的 Json 示例

[ "query": "age", "type": "numeric", "min": 5, "max": 99 , “查询”:“诊断”,“类型”:“字符串”,“输入”:[“husten”, "schnupfen"] ]

我写的反序列化代码是:

public class Query
    private String query;
    private String type;
    // Getters and Setters and constructor


public class QueryString extends Query implements Serializable 
    private List<String> in;
    private String like;
    // Getters and Setters and constructor


public class QueryNum extends Field implements Serializable 
    private Number min;
    private Number max;
    // Getters and Setters and constructor

使用 ObjectMapper 的序列化按预期工作,但是编译器通过反序列化给我一个无法识别的值(这是我的子类的字段)。

我想得到一个对象列表(查询) 包含 QueryString 和 QueryNum 的列表。

Java 中的 Jackson Json 有可能吗?

对于我使用的反序列化:

    ObjectMapper mapper = new ObjectMapper();

    List<Query> queries= Arrays.asList(mapper.readValue(JsonString, Query[].class));

提前致谢

【问题讨论】:

【参考方案1】:

如果您在每个对象中有一个字段可用于识别要构建的对象,则可以使用注解@JsonTypeInfo

注释用于配置类型信息是否以及如何与 JSON 序列化和反序列化一起使用的详细信息,以保留有关 Object 实例的实际类的信息。这对于多态类型是必要的,也可能需要链接抽象声明的类型和匹配的具体实现。

@JsonSubTypes:

与 JsonTypeInfo 一起使用的注解指示可序列化多态类型的子类型,并关联 JSON 内容中使用的逻辑名称(这比使用物理 Java 类名称更便携)。

或者JsonTypeName:

注解用于绑定被注解的类所具有的逻辑名。与 JsonTypeInfo(特别是其 JsonTypeInfo.use() 属性)一起使用,以建立类型名称和类型之间的关系。

基本上,您需要在@JsonTypeInfo 中定义一个包含与要实例化的类相关信息的属性,并在@JsonSubTypes 中定义可能的值

这是一个例子

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = As.PROPERTY, 
  property = "type")
@JsonSubTypes(
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat")
)
public class Animal 
    // The property type is used to know what object instantiate
    private String type;
    ...


@JsonTypeName("dog")
public class Dog extends Animal 
    ...


@JsonTypeName("cat")
public class Cat extends Animal 
    ...


如果您没有此类字段,则需要创建自定义反序列化器。

另一种方法是将您的记录转换为Map 的列表,因为Map 可以包含任何有效对象。

【讨论】:

非常感谢。它奏效了。 我现在唯一遇到的问题是“type”的值总是反序列化为 null 而不是实际值(在您的示例中为“dog”和“cat”)。 我刚刚添加了@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type", visible=true),它现在按预期工作

以上是关于使用 Jackson 反序列化对象列表的主要内容,如果未能解决你的问题,请参考以下文章

Jackson - 将内部对象列表反序列化为更高级别的列表

使用 Jackson 反序列化重复键以列出

Jackson 没有反序列化已序列化的通用列表

如何使用 Jackson 反序列化来自 json 对象的对象数组

无法使用 Jackson XML 直接在根元素内反序列化列表

使用 writeValueAsString 序列化对象后 Jackson 反序列化失败