簡體   English   中英

沒有注釋的Jackson中的多態反序列化

[英]Polymorphic deserialization in Jackson without annotations

我有一個CloudEvent<T>類,它使用傑克遜(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;
}

然后反序列化為:

String cloudEventJson1 = "{\"eventType\":\"event-1\",\"data\":{\"id\":\"123\",\"details\":\"detail1\"}}";

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

所有這些都很好。 但是由於某些限制,我無法在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);

但是,使用與上述相同的方法反序列化將不起作用。 它正在讀取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]

這也為所有輸入類配置了ObjectMapper。 是否可以將此typeResolverBuildersubtypes連接到CloudEvent.class (就像注釋方法那樣)。

即使您無法修改類,您仍然可以依靠注釋。 Jackson支持一項稱為混合功能的功能:您可以將其視為一種面向方面的方式,可以在運行時添加更多注釋,以增強靜態定義的注釋。

首先定義一個接口,如下所示:

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以將定義的接口用作實際類/接口的混合:

ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(CloudEvent.class, CloudEventMixIn.class);

addMixIn(Class<?> target, Class<?> mixinSource)方法文檔中:

用於添加混合注釋以用於擴展指定的類或接口的方法。 來自mixinSource所有注釋都將覆蓋target (或其超類型)具有的注釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM