Raz*_*zor 7 java spring json jackson deserialization
我有一个CloudEvent<T>使用 Jackson (2.9.0 - 最新版本)进行多态反序列化的类,如下所示:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CloudEvent<T> {
@NonNull
private String eventType;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "eventType",
defaultImpl = Void.class)
@JsonSubTypes({
@JsonSubTypes.Type(value = MyEvent1.class, name = "event-1"),
@JsonSubTypes.Type(value = MyEvent2.class, name = "event-2")
})
private T data;
}
Run Code Online (Sandbox Code Playgroud)
然后反序列化为:
String cloudEventJson1 = "{\"eventType\":\"event-1\",\"data\":{\"id\":\"123\",\"details\":\"detail1\"}}";
CloudEvent deserializedEvent1 = objectMapper.readValue(cloudEventJson1, CloudEvent.class); //without subtypes
Run Code Online (Sandbox Code Playgroud)
这一切都运行良好。但由于一些限制,我无法在 CloudEvent 类上使用注释(由外部依赖项提供)。
所以我这样配置 ObjectMapper:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerSubtypes(new NamedType(MyEvent1.class, "event-1"));
objectMapper.registerSubtypes(new NamedType(MyEvent2.class, "event-2"));
TypeResolverBuilder typeResolverBuilder = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
.init(JsonTypeInfo.Id.NAME, null) //CLASS works
.inclusion(JsonTypeInfo.As.EXTERNAL_PROPERTY)
.typeProperty("eventType")
.typeIdVisibility(true)
// .defaultImpl(Void.class);
objectMapper.setDefaultTyping(typeResolverBuilder);
Run Code Online (Sandbox Code Playgroud)
但是用与上面相同的方法反序列化不起作用。它正在读取eventType但无法与注册的子类型匹配。我不能在反序列化中使用泛型或 TypeReferance,因为我需要用于spring-integration读取仅接受主类的事件;反序列化后手动完成模式匹配。
例外:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'event-1' as a subtype of [simple type, class java.lang.Object]: known type ids = [] (for POJO property 'data')
at [Source: (String)"{"eventType":"event-1","data":{"id":"123","details":"detail1"}}"; line: 1, column: 271]
Run Code Online (Sandbox Code Playgroud)
这也是为所有输入类配置 ObjectMapper。是否可以将其连接到typeResolverBuilder(就像注释方式一样)。subtypesCloudEvent.class
即使您无法修改您的类,您仍然可以依赖注释。Jackson 支持一种称为mix-ins的功能:您可以将其视为一种面向方面的方式,在运行时添加更多注释,以增强静态定义的注释。
首先定义一个接口如下:
public interface CloudEventMixIn<T> {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "eventType",
defaultImpl = Void.class)
@JsonSubTypes({
@JsonSubTypes.Type(value = MyEvent1.class, name = "event-1"),
@JsonSubTypes.Type(value = MyEvent2.class, name = "event-2")
})
public T getData();
}
Run Code Online (Sandbox Code Playgroud)
然后配置ObjectMapper为使用定义的接口作为实际类/接口的混合:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(CloudEvent.class, CloudEventMixIn.class);
Run Code Online (Sandbox Code Playgroud)
从addMixIn(Class<?> target, Class<?> mixinSource)方法文档中:
用于添加混合注释以用于增强指定类或接口的方法。所有注释都
mixinSource被用来覆盖target(或其超类型)具有的注释。
| 归档时间: |
|
| 查看次数: |
5047 次 |
| 最近记录: |