簡體   English   中英

如何使用 Jackson 的 objectMapper 反序列化接口字段?

[英]How to deserialize interface fields using Jackson's objectMapper?

ObjectMapperreadValue(InputStream in, Class<T> valueType)函數需要類。 但是如果我在內部傳遞的類有一些接口作為數據成員,我該如何使用它。

雖然我可以理解這個異常背后的原因,因為傑克遜沒有得到傳遞類的內部接口的具體類,但我的問題是如何解決它? 那我該如何反序列化呢? 我試圖反序列化的類是:

class BaseMetricImpl<N> implements Metric<N> {
    protected MetricValueDescriptor descriptor;
}

這里MetricValueDescriptor是一個接口,所以這給了我以下錯誤:-

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of MetricValueDescriptor, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: java.io.ByteArrayInputStream@2ede2c9f; line: 1, column: 2] (through reference chain: SingleValueMetricImpl["descriptor"])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:624)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:115)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2793)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1989)

Jackson 顯然不能構造MetricValueDescriptor對象,因為它是一個接口。 您需要在 json 和 ObjectMapper 中包含其他信息,以告訴 jackson 如何從中構造對象。 這是一種方法,假設MVDImpl是一個實現MetricValueDescriptor的具體類:

您可以通過 json 本身中的字段告訴 Jackson 所需的類型信息,例如"type" 為此,您需要在界面中使用JsonTypeInfoJsonSubTypes注釋。 例如,

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @Type(value = MVDImpl.class, name = "mvdimpl") })
interface MetricValueDescriptor
{
   ...
}

您還需要在 json 中添加一個"type":"mvdimpl"字段。

我打算將您指向官方文檔以獲取更多信息,但后來我發現了一個很好的博客,涵蓋了這個主題 - Deserialize JSON with Jackson 它非常全面地涵蓋了這個主題,並附有示例。 所以如果你需要更多的定制,你一定要閱讀它。

我認為這是兩種方式之一,但它們都需要您手動創建一個實現您的接口的具體類。

  1. 使用 @Hari Menon 的答案並使用@JsonSubTypes 如果您可以引入類型字段或其他內容來觸發要使用的實現,則此方法有效。
  2. 使用@JsonDeserialize告訴 jackson 它默認使用的具體類。
@JsonDeserialize(as = MVDImpl.class)
interface MetricValueDescriptor
{
   ...
}

這里有一個更徹底的解釋: https : //zenidas.wordpress.com/recipes/jackson-deserialization-of-interfaces/

和文檔: https : //fasterxml.github.io/jackson-databind/javadoc/2.8/com/fasterxml/jackson/databind/annotation/JsonDeserialize.html

您不需要更改代碼,您可以在映射器上以編程方式設置它:

static setup() {
   final var simpleModule = new SimpleModule()
        .addAbstractTypeMapping(<Interface>.class, <Implementation>.class);

   objMapper = new ObjectMapper()
        .registerModule(new Jdk8Module()) // You probably want this as well
        .registerModule(simpleModule);
}

暫無
暫無

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

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