首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >没有注释的Jackson中的多态反序列化

没有注释的Jackson中的多态反序列化
EN

Stack Overflow用户
提问于 2019-03-19 14:28:27
回答 1查看 3.8K关注 0票数 7

我有一个CloudEvent<T>类,它使用Jackson (2.9.0 -最后一个版本)进行多态反序列化,如下所示:

代码语言:javascript
复制
@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;
}

然后反序列化为:

代码语言:javascript
复制
String cloudEventJson1 = "{\"eventType\":\"event-1\",\"data\":{\"id\":\"123\",\"details\":\"detail1\"}}";

CloudEvent deserializedEvent1 = objectMapper.readValue(cloudEventJson1, CloudEvent.class);   //without subtypes

这一切都很好。但是由于一些限制,我不能在CloudEvent类上使用注释(由外部依赖关系提供)。

因此,我将ObjectMapper配置如下:

代码语言:javascript
复制
    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);

但是,使用与上面相同的方法反序列化不起作用。它正在读取eventType,但它无法与已注册的子类型匹配。我不能在反序列化中使用泛型或TypeReferance,因为我需要使用spring-integration读取只接受主类的事件;反序列化之后手动完成模式匹配。

例外:

代码语言:javascript
复制
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]

这也是为所有输入类配置ObjectMapper。是否可以将这个typeResolverBuildersubtypes连接到CloudEvent.class (就像注释方法那样)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-19 14:33:17

即使不能修改类,仍然可以依赖注释。Jackson支持一个名为混合的特性:您可以认为它是一种面向方面的方式,可以在运行时添加更多的注释,以增强静态定义的注释。

首先,按以下方式定义接口:

代码语言:javascript
复制
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();
}

然后将ObjectMapper配置为使用定义的接口作为实际类/接口的混合:

代码语言:javascript
复制
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(CloudEvent.class, CloudEventMixIn.class);

来自addMixIn(Class target, Class mixinSource)方法文档:

方法用于添加混合注释,用于增强指定的类或接口。来自mixinSource的所有注释都被用来覆盖target (或其超级类型)所具有的注释。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55243350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档