簡體   English   中英

Spring-boot 和 Jackson 屬性中的多態性

[英]Spring-boot and polymorphism in Jackson properties

我很難使用 Spring-boot 為 Synology FileStation API 創建 REST 客戶端。 事實上,API 使用相同的屬性來存儲不同類型的對象。 使用的屬性是數據,它可以存儲sid或搜索結果的內容,如文件共享。

對於搜索結果:

{
  "data": {
    "offset": 0,
    "shares": [
      {
        "isdir": true,
        "name": "config",
        "path": "/config"
      },
      ...
    ],
    "total": 19
  },
  "success": true
}

登錄結果:

{
  "data": {
    "sid": "blablablabla",
  },
  "success": true
}

對於錯誤的登錄錯誤:

{
  "error": {
    "code": 400,
  },
  "success": false
}

我嘗試為每種類型的響應設計 model,但我找不到使用 Jackson 反序列化它的正確方法。

為簡單起見,用於接收響應的class為 Reponse ,響應中有一個成功字段,以及另外兩個字段:數據錯誤 根據響應,要實例化的數據LoginResponseListShares object。

這是我的課程的代碼:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
    @JsonProperty("success")
    private boolean success;
    @JsonProperty(value = "data")
    private Data data;
    @JsonProperty(value = "error")
    private Error error;
    ...
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class Error {
    private int code;
    private Collection<ErrorInfo> errors;

    public Error( int code, Collection<ErrorInfo> errors) {
        super();
        this.code = code;
        this.errors = errors;
    }
    ...
}


@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = LoginResponse.class),
        @JsonSubTypes.Type(value = ListShares.class),
})
public abstract class Data {

}

@JsonTypeName("LoginResponse")
public class LoginResponse extends Data {

    @JsonProperty("sid")
    private String sid;

    public LoginResponse() {
        super();
    }
    ...
}


@JsonTypeName("ListShares")
public class ListShares extends Data {

    @JsonProperty("offset")
    private int offset;
    @JsonProperty("total")
    private int total;
    @JsonProperty("shares")
    private Set<Share> shares;

    public ListShares() {
        super();
    }

    public ListShares(int offset, int total, Set<Share> shares) {
        super();
        this.offset = offset;
        this.total = total;
        this.shares = shares;
    }

我得到這個例外:

Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.heavyrage.syno.apis.genericresponses.Response]: missing type id property 'data'
 at [Source: (PushbackInputStream); line: 1, column: 38]
    at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1794) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1323) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:303) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:166) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:107) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1209) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3487) ~[jackson-databind-2.11.1.jar:2.11.1]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:273) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ... 17 common frames omitted

有人知道是否可以正確實例化數據object(實例化 LoginResponse 或 ListShare)以填充響應 object 的“數據”屬性?

我終於從 Jackson 問題跟蹤器中找到了這個答案。 關鍵是實例化數據object時要調用的解串器,因此返回正確的實現class並且Jackson可以實例化它。

https://stackoverflow.com/a/50013090/1030527

無論如何,對 Response class 使用組合是一個好主意,因為它反映了它與 Data 和 Error 類的 HasA 關系。

對於數據 class 本身,使用與 Java 接口的組合導致另一個由 Jackson 試圖實例化接口 ZA2DC21ED24F8 引起的異常。

暫無
暫無

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

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