杰克逊注释中的多态性:@JsonTypeInfo用法

我想知道注释是否可以用于接口。我有一组应该序列化和反序列化的类。@JsonTypeInfo

这就是我正在努力做的事情。我有两个实现类,实现。某些模型类具有实现类型的接口引用。我想基于多态性反序列化对象Sub1Sub2MyInt

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.WRAPPER_OBJECT)
@JsonSubTypes({
    @Type(name="sub1", value=Sub1.class), 
    @Type(name="sub2", value=Sub2.class)})
public interface MyInt{
}

@JsonTypeName("sub1")
public Sub1 implements MyInt{
}

@JsonTypeName("sub2")
public Sub2 implements MyInt{
}

我得到以下内容:JsonMappingException

意外的令牌 (END_OBJECT),预期FIELD_NAME:需要包含类型 id 的 JSON 字符串


答案 1

@JsonSubTypes.Type必须具有如下所示的值和名称,

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.WRAPPER_OBJECT, property="type")
@JsonSubTypes({       
    @JsonSubTypes.Type(value=Dog.class, name="dog"),
    @JsonSubTypes.Type(value=Cat.class, name="cat")       
}) 

在子类中,用于说出名称。
值 和 将在名为 的属性中设置。@JsonTypeName("dog")dogcattype


答案 2

是的,它既可以用于抽象类,也可以用于接口。

请考虑下面的代码示例

假设我们有一个枚举、接口和类

enum VehicleType {
    CAR,
    PLANE
}

interface Vehicle {
    VehicleType getVehicleType();
    String getName();
}


@NoArgsConstructor
@Getter
@Setter
class Car implements Vehicle {
    private boolean sunRoof;
    private String name;

    @Override
    public VehicleType getVehicleType() {
        return VehicleType.Car;
    }
}

@NoArgsConstructor
@Getter
@Setter
class Plane implements Vehicle {
    private double wingspan;
    private String name;

    @Override
    public VehicleType getVehicleType() {
        return VehicleType.Plane;
    }
}

如果我们尝试将此 json 反序列化为List<Vehicle>

[
  {"sunRoof":false,"name":"Ferrari","vehicleType":"CAR"}, 
  {"wingspan":19.25,"name":"Boeing 750","vehicleType":"PLANE"}
]

那么我们将得到错误

abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

要解决此问题,只需在界面中添加以下和注释,如下所示JsonSubTypesJsonTypeInfo

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
        property = "vehicleType")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Car.class, name = "CAR"),
        @JsonSubTypes.Type(value = Plane.class, name = "PLANE")
})
interface Vehicle {
    VehicleType getVehicleType();
    String getName();
}

这样,反序列化将与接口一起使用,您将获得一个返回List<Vehicle>

您可以在此处查看代码 - https://github.com/chatterjeesunit/java-playground/blob/master/src/main/java/com/play/util/jackson/PolymorphicDeserialization.java


推荐