java - Jackson 3.1.1 列表多态类型的子类型异常缺少类型 ID?

标签 java json jackson jackson-databind

我有一个我创建的抽象类的具体对象。

我在抽象类和子类上使用注释,但 JSON 输出看起来不正确,并且我不断收到反序列化异常。

我仍在学习 Jackson,不幸的是,许多有关该主题的教程都已经过时了。

下面是我的对象映射器位于底部的类:

抽象类:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "BTRFSPhysicalLocationItem")
@JsonSubTypes({
    @Type(name = "Snapshot", value = Snapshot.class),
    @Type(name = "Backup", value = Backup.class),
    @Type(name = "Subvolume", value = Subvolume.class)})
public abstract class BTRFSPhysicalLocationItem {

    private final String name;
    @JsonProperty
    private final Path location;

    /**
     * Makes a new subvolume instance with the specified location. May or may
     * not actually exist.
     *
     * @param location The location of the subvolume
     */
    @JsonCreator
    protected BTRFSPhysicalLocationItem(@JsonProperty(value = "location") Path location) {
        this.location = location;
        this.name = location.getFileName().toString();
    }

具体类:

public class Subvolume extends BTRFSPhysicalLocationItem {

    /**
     * Creates a new subvolume with the specified path.The subvolume may or may
     * not exist at this point.
     *
     * @param location
     */
    @JsonCreator
    public Subvolume(@JsonProperty Path location) {
        super(location);
    }

对象映射器 block :

ObjectMapper MAPPER = new ObjectMapper();
List<Subvolume> SUBVOLUME_LIST = new ArrayList<>();
//Subvolume is populated by other methods it's not worth showing them here
System.out.println("\n\n");
                MAPPER.writeValue(System.out, SUBVOLUME_LIST);
                System.out.println("\n\n\n");
                var s = MAPPER.writeValueAsString(SUBVOLUME_LIST);
                List<Subvolume> list = MAPPER.readValue(s, new TypeReference<List<Subvolume>>() {
                });

输出 JSON: [{"name":"WanderingEcho","location":"file:///home/sarah/NetBeansProjects/WanderingEcho/"}]

异常(exception):

Aug 05, 2019 4:55:14 PM com.protonmail.sarahszabo.wanderingecho.btrfs.BTRFS <clinit>
SEVERE: null
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.protonmail.sarahszabo.wanderingecho.btrfs.subvolume.Subvolume]: missing type id property 'BTRFSPhysicalLocationItem'
 at [Source: (String)"[{"name":"WanderingEcho","location":"file:///home/sarah/NetBeansProjects/WanderingEcho/"}]"; line: 1, column: 89] (through reference chain: java.util.ArrayList[0])

其他答案,例如Jackson deserialization of polymorphic types建议使用 ObjectMapper 方法,但根据我读过的教程,这应该不是必需的。

不确定我的注释做错了什么。

最佳答案

在您的 json 中您缺少 BTRFSPhysicalLocationItem - 想想看 - Jackson 如何知道你期望什么实现?

它应该看起来像

[
    {
        "BTRFSPhysicalLocationItem": "Subvolume",
        "name": "WanderingEcho",
        "location":"file:///home/sarah/NetBeansProjects/WanderingEcho/"
    }
]

如果您希望 Jackson 在序列化对象时包含类型,您还需要添加 JsonTypeInfo.As.PROPERTYinclude作为 @JsonTypeInfo 的参数注释如

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "BTRFSPhysicalLocationItem")
<小时/>

编辑 好吧,看来我已经弄清楚了 - 您不生成属性的问题与 Java 类型删除有关,并且得到了很好的描述 here

tldr; jackson 在理解类型方面存在问题 - 似乎 List<Subvolume>对于他来说没有提供元素的类型。因为他不知道类型,所以他不会序列化它

解决方案是创建一个扩展 ArrayList<Subvolume> 的辅助类喜欢

public class SubvolumeList extends ArrayList<Subvolume> {}
<小时/>

此外,您的代码中存在一些问题 - 一个是您应该使用 use = JsonTypeInfo.Id.NAME@JsonTypeInfo如果您想按属性值(如 Subvolume )而不是按包/类字符串文字反序列化

第二个是你应该命名 @JsonProperty@JsonCreator参数列表如 @JsonProperty(value = "location")

关于java - Jackson 3.1.1 列表多态类型的子类型异常缺少类型 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57366190/

相关文章:

javascript - 我是否错误地使用了 jQuery .each 函数?

javascript - 从 json 填充可观察数组

java - 处理 jackson 异常

java - 具有嵌套参数类的 Jackson Json

java - 自定义 Spring Data Rest 投影

java |如何使用反射和 RTTI 计算所有方法?

java - 如何读取旋转器并从编辑文本获取数据到 TextView ?

java - 将根元素添加到生成的 json 对象中

java - 无法使用 mailR 包通过 Outlook.com 发送电子邮件

java - TableLayout 中表格行的索引