57

我想知道@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:需要包含类型 id 的 JSON 字符串

4

2 回答 2

50

@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

于 2012-08-03T15:14:09.647 回答
1

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

考虑以下代码示例

假设我们有一个 enum 、 interface 和 classes

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

于 2020-08-06T12:34:15.033 回答