json Jackson3.1.1列表的多态类型是否缺少子类型异常的类型ID?

j2datikz  于 2023-05-19  发布在  其他
关注(0)|答案(2)|浏览(208)

我有一个抽象类的具体对象。
我在抽象类和子类上使用了注解,但是JSON输出看起来不太对,而且反序列化时总是出现异常。
我还在学习Jackson,不幸的是,很多关于这个主题的教程已经过时了。
下面是我的对象Map器在底部的类:

抽象类:

@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);
    }

Objectmapper块:

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/"}]

例外情况:

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方法,但根据我读过的教程,这应该不是必要的。
不知道我做错了什么注解。

ybzsozfc

ybzsozfc1#

在您的json中,您缺少了BTRFSPhysicalLocationItem-请考虑一下-Jackson如何知道您期望的实现?
它应该看起来像

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

如果希望Jackson在序列化对象时包含该类型,则还需要添加JsonTypeInfo.As.PROPERTY as include作为@JsonTypeInfo注解的参数,如

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "BTRFSPhysicalLocationItem")

EDITok似乎我已经弄明白了--你的问题是不生成属性,这与Java类型擦除和here有关。

tldr;Jackson有不理解类型的问题-似乎List<Subvolume>对他来说没有提供元素的类型。因为他不知道是什么类型他就不连载了
解决方案是创建一个helper类,它将扩展ArrayList<Subvolume>,如

public class SubvolumeList extends ArrayList<Subvolume> {}

另外,您的代码中还有一些问题-其中之一是,如果您希望按属性值(如Subvolume)而不是按包/类字符串文字进行反序列化,则应在@JsonTypeInfo中使用use = JsonTypeInfo.Id.NAME
第二种方法是在@JsonCreator参数列表中将@JsonProperty命名为@JsonProperty(value = "location")

soat7uwm

soat7uwm2#

当我偶然发现这篇文章时,我也遇到了类似的问题。我有

@JsonTypeInfo(
  use = Id.MINIMAL_CLASS,
  property = "@class"
)
public class MyClass {
  public int myInt;
}

然后

public class MyIntWrapper {
  public Optional<MyInt> maybeMyInt;
}

我想通过电线发送MyIntWrapper。它将示例正确地序列化为JSON,但存在反序列化问题。我在看

com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.coder34.MyIntWrapper$Json]: missing type id property '@class' (for POJO property '#temporary-name')
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.coder34.MyIntWrapper$Json["maybeMyInt"])

按照@m.antkowicz关于类型擦除的链接,我尝试将其添加到字段中。因此,我删除了MyClass中的注解,并将其添加到字段maybeMyInt中-

public class MyClass {
  public int myInt;
}
public class MyIntWrapper {
  @JsonTypeInfo(
    use = Id.MINIMAL_CLASS,
    property = "@class"
  )
  public Optional<MyInt> maybeMyInt;
}

而且成功了

相关问题