2013-10-15 18 views
11

ObjectMapperreadValue(InputStream in, Class<T> valueType)関数には、クラスが必要です。しかし、私が内部的に渡しているクラスがデータメンバとしていくつかのInterfaceを持っているなら、私はどのように使用しますか?JacksonのobjectMapperを使用してインターフェースフィールドを逆シリアル化する方法は?

私はこの例外の背後にある理由を理解することができますが、ジャクソンは渡されたクラスの内部インターフェイスの具体的なクラスを取得していないため、私の質問はそれを解決する方法ですか? どうすればそれを逆シリアル化できますか?私はデシリアライズしようとしているクラスは、次のとおりです。ここで

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: [email protected]; 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) 
+0

サンプルコードを更新して、エラースタックトレースを完了できますか? – vels4j

+0

@ vels4j小さなコードサンプルと例外を入れる質問を編集しました – Naman

答えて

27

ジャクソンは明らかにMetricValueDescriptorオブジェクトを作成することはできません。 jacksonにオブジェクトを構築する方法を伝えるには、jsonとObjectMapperに追加情報が必要です。ここではそれを行うための一つの方法である、MVDImplMetricValueDescriptorを実装した具象クラスであると仮定すると:

あなたは、JSON自体にフィールドを介しジャクソンに必要な型情報を伝えることができ、"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"フィールドを追加する必要があります。

詳細については、official docを指摘していましたが、このトピックをカバーする優れたブログを見つけました。Deserialize JSON with Jacksonそれは、このトピックをかなり包括的に、そして例題とともに扱います。カスタマイズが必要な方はぜひ読んでください。

+2

私は同じ問題に直面していますが、「スーパークラス」は私のものではなく、変更することはできません。その場合、「ジャクソン」マップをどのようにして適切な「サブクラス」にすることができますか? – lvarayut

+1

@lvarayut [Jackson Mixin Annotations](http://wiki.fasterxml.com/JacksonMixInAnnotations)を使用して、変更不可能なクラスに注釈を追加することができます。 – mucaho

+0

別の方法(少し関与する)は、「ObjectMapper」を介して有効にされる、いわゆる「デフォルトの型付け」を使用することです。アノテーションなしで、クラスのカテゴリの型情報を有効に含めることができます。デフォルトでは、「すべての非具体的な型」、「すべての非最終型」などの選択肢がいくつかありますが、独自の戦略を実装することもできます。 – StaxMan

関連する問題