Java Jackson序列化抽象类列表

时间:2018-12-21 21:14:42

标签: java json jackson jackson2

场景

想象一下,我有一个名为InfoItem的抽象类,每个从其继承的类都是不同类型的信息类型,稍后将用于帮助我进行分类。

每个InfoItem都有一个timestamp作为属性(这个InfoItem何时到达)?

注意:在此示例中,我使用的是 Lombok

@Data
@JsonTypeInfo(use = Id.NAME, visible = true, property = "@type")
public abstract class InfoItem {
    private LocalDateTime timestamp;
}

我有2个扩展该类的类:AlphaBeta。 每个类都有多个属性,它们之间没有共同的属性:

@JsonTypeName("alpha")
@Data
public class Alpha extends InfoItem {
    private int x;
    private long y;
}

@JsonTypeName("beta")
@Data
public class Beta extends InfoItem {
    private bool isOk;
}

现在想象一下,我创建了一个InfoItem个项目的列表:

list[0] = Alpha(x = 10, y = 20)
list[1] = Beta(isOk = false)

问题

如果以上列表另存为名为lst的变量,然后运行以下命令:

ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(lst);
System.out.println(s);

我会得到这个:

[
    {
        "x": 10,
        "y": 20
    },
    {
        "isOk": false
    }
]

代替:

[
    {
        "@type": "alpha",
        "x": 10,
        "y": 20
    },
    {
        "@type": "beta",
        "isOk": false
    }
]

当我直接在ObjectMapper上运行List而不是我创建并在列表中放置的类时,就会发生这种情况。

案例:列出我创建的课程

如果我创建一个名为FooBar的类,它具有一个属性lst(类型为List,与上面相同):

@Data
public class FooBar {
    private List<InfoItem> items;
}

然后我做

FooBar bar = new FooBar();
bar.setItems(lst);

ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(lst);
System.out.println(s);

我会得到:

{
    "items": [
        {
            "@type": "alpha",
            "x": 10,
            "y": 20
        },
        {
            "@type": "beta",
            "isOk": false
        }
    ]
}

2 个答案:

答案 0 :(得分:1)

如果您用以下内容注释abstract类,则可以完成此操作(您可能需要根据需要对其进行调整):

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = Alpha.class, name = "_type"),
  @JsonSubTypes.Type(value = Beta.class, name = "_type"),
})

生成JSON时,它将插入一个_typeAlpha等的FQDN类值的Beta密钥。在您的用例中,它应该工作类似。 / p>

查看this是否有助于获得更多背景知识。不久前我在做类似的事情–我还没有更新问题:)

答案 1 :(得分:0)

几天后我找到了解决方法:

public static <T> Optional<String> toJson(final ObjectMapper mapper, final TypeReference<T> type, final T object) {
    try {
        return Optional.ofNullable(mapper.writer().forType(type).writeValueAsString(object));
    } catch (JsonProcessingException e) {
        return Optional.empty();
    }
}

public static void main(String[] args) {
    List<InfoItem> items = new ArrayList<>();
    // Set values in items...

    ObjectMapper mapper = new ObjectMapper();
    Optional<String> json = toJson(mapper, new TypeReference<List<InfoItem>>() {}, items);
    json.ifPresent(x -> System.out.println(x));
}