jackson注释中的多态性:@JsonTypeInfo用法

时间:2012-08-03 15:09:37

标签: java polymorphism jackson deserialization

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

这是我正在尝试做的事情。我有两个实现类Sub1Sub2实现MyInt。某些模型类具有实现类型的接口参考。我想基于多态

反序列化对象
@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:需要JSON字符串   包含类型ID

2 个答案:

答案 0 :(得分:45)

@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")来表示名称 值dogcat的值将在名为type的属性中设置。

答案 1 :(得分:1)

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

考虑以下代码示例

假设我们有一个enum,接口和类

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