深入解析Jackson的@JsonTypeInfo与@JsonSubTypes

在Java的序列化与反序列化过程中,Jackson库提供了强大的功能来处理复杂的数据类型,尤其是在处理多态时。本文将详细探讨@JsonTypeInfo@JsonSubTypes注解的使用,并通过一个实例来展示如何在Jackson中使用这些注解。

背景知识

在JSON序列化过程中,如果使用Java类的全限定名作为类型标识符,这在非Java客户端消费序列化后的JSON时可能不是一个好的选择。为了解决这个问题,我们可以使用"逻辑类型名称"作为类型标识符。

使用@JsonTypeInfo与@JsonSubTypes

@JsonTypeInfo注解用于指定如何序列化和反序列化类型信息。当设置use = JsonTypeInfo.Id.NAME时,类型名称将被用作类型标识符。为了将这个名称解析为实际的具体类型,我们需要使用@JsonSubTypes注解。

实例分析

假设我们有一个Shape抽象类,它有两个子类RectangleCircle。我们希望在序列化时使用逻辑类型名称,而不是Java类的全限定名。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Rectangle.class),
    @JsonSubTypes.Type(value = Circle.class)
})
public abstract class Shape { }

@JsonTypeName("rectangle")
public class Rectangle extends Shape {
    private int w;
    private int h;
    // 构造函数和getter/setter省略
}

@JsonTypeName("circle")
public class Circle extends Shape {
    private int radius;
    // 构造函数和getter/setter省略
}

public class View {
    private List<Shape> shapes;
    // 构造函数和getter/setter省略
}

序列化与反序列化示例

ExampleMain类中,我们创建了一个View对象,其中包含RectangleCircle对象的列表。然后使用ObjectMapper进行序列化和反序列化。

public class ExampleMain {
    public static void main(String[] args) throws IOException {
        View v = new View();
        v.setShapes(new ArrayList<>(List.of(Rectangle.of(3, 6), Circle.of(5))));
        System.out.println("-- serializing --");
        ObjectMapper om = new ObjectMapper();
        String s = om.writeValueAsString(v);
        System.out.println(s);
        System.out.println("-- deserializing --");
        View view = om.readValue(s, View.class);
        System.out.println(view);
    }
}

输出结果

序列化输出:

{"shapes":[{"@type":"rectangle","w":3,"h":6},{"@type":"circle","radius":5}]}

反序列化输出:

View{shapes=[Rectangle{w=3, h=6}, Circle{radius=5}]}

自定义类型属性名称

如果我们想要自定义类型属性的名称,而不是使用默认的@type,可以通过property元素来指定。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "typeName")
...

这将序列化输出为:

{"shapes":[{"typeName":"rectangle","w":3,"h":6},{"typeName":"circle","radius":5}]}

使用类型包装器

除了JsonTypeInfo.As.PROPERTY,我们还可以使用JsonTypeInfo.As.WRAPPER_OBJECTJsonTypeInfo.As.WRAPPER_ARRAY来包装类型信息。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
...

这将序列化输出为:

{"shapes":[{"rectangle":{"w":3,"h":6}},{"circle":{"radius":5}}]}

项目依赖和技术

  • jackson-databind 2.9.6: Jackson的核心数据绑定功能。
  • JDK 10
  • Maven 3.3.9

通过本文的分析,我们可以看到@JsonTypeInfo@JsonSubTypes在处理多态和类型安全方面的重要作用。希望这个实例能够帮助你更好地理解和使用这些注解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

t0_54coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值