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

Chr*_*ris 51 java polymorphism jackson deserialization

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

这就是我想要做的.我有两个实现类Sub1,Sub2实现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{
}
Run Code Online (Sandbox Code Playgroud)

我得到以下内容JsonMappingException:

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

Sen*_*mar 46

@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")       
}) 
Run Code Online (Sandbox Code Playgroud)

在子类中,@JsonTypeName("dog")用来表示名称.
dogcat将在指定的属性设置type.

  • 但是,如果其他人试图实现您的界面呢?如果不在接口文件中添加注释,则无法将名为"sub3"的新具体类型解组为MyInt. (5认同)
  • 有没有人知道JsonTypeInfo是否可以应用于接口? (2认同)
  • 是的,@ JsonTypeInfo可以用于接口,如果这有帮助(杰克逊的注释处理支持继承) (2认同)

小智 5

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

考虑以下代码示例

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

[
  {"sunRoof":false,"name":"Ferrari","vehicleType":"CAR"}, 
  {"wingspan":19.25,"name":"Boeing 750","vehicleType":"PLANE"}
]
Run Code Online (Sandbox Code Playgroud)

那么我们会得到错误

abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
Run Code Online (Sandbox Code Playgroud)

要解决这个问题,只需在界面中添加以下内容JsonSubTypes和注释,如下所示JsonTypeInfo

@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();
}
Run Code Online (Sandbox Code Playgroud)

这样,反序列化将与接口一起工作,您将得到一个List<Vehicle>返回值

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