Sar*_*abo 4 java json jackson jackson-databind
我有一个我创建的抽象类的具体对象。
我在抽象类和子类上使用注释,但 JSON 输出看起来不正确,并且我不断收到反序列化异常。
我仍在学习杰克逊,不幸的是很多关于这个主题的教程都已经过时了。
以下是我的对象映射器位于底部的类:
抽象类:
@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();
}
Run Code Online (Sandbox Code Playgroud)
具体类:
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);
}
Run Code Online (Sandbox Code Playgroud)
对象映射器块:
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>>() {
});
Run Code Online (Sandbox Code Playgroud)
输出 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])
Run Code Online (Sandbox Code Playgroud)
其他答案(例如多态类型的 Jackson 反序列化)建议使用这些ObjectMapper方法,但根据我读过的教程,这应该不是必需的。
不确定我的注释做错了什么。
在你的例子中,json你错过了BTRFSPhysicalLocationItem- 想想看 - 杰克逊应该如何知道你期望什么实现?
它应该看起来像
[
{
"BTRFSPhysicalLocationItem": "Subvolume",
"name": "WanderingEcho",
"location":"file:///home/sarah/NetBeansProjects/WanderingEcho/"
}
]
Run Code Online (Sandbox Code Playgroud)
如果您希望 Jackson 在序列化对象时包含类型,您还需要添加JsonTypeInfo.As.PROPERTYas作为注释include的参数,例如@JsonTypeInfo
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "BTRFSPhysicalLocationItem")
Run Code Online (Sandbox Code Playgroud)
编辑好吧,似乎我已经弄清楚了 - 您不生成属性的问题与 Java 类型擦除有关,并且在这里得到了很好的描述。
太棒了;杰克逊在理解类型方面存在问题 -List<Subvolume>对他来说似乎没有提供元素的类型。因为他不知道类型,所以不会序列化它
解决方案是创建一个辅助类,该类将扩展ArrayList<Subvolume>为
public class SubvolumeList extends ArrayList<Subvolume> {}
Run Code Online (Sandbox Code Playgroud)
另外,您的代码中存在一些问题 - 一个是如果您想按属性值(如)而不是按包/类字符串文字反序列化,则应该使用use = JsonTypeInfo.Id.NAMEin@JsonTypeInfoSubvolume
其次,您应该@JsonProperty在@JsonCreator参数列表中命名,例如@JsonProperty(value = "location")
| 归档时间: |
|
| 查看次数: |
45034 次 |
| 最近记录: |