36

ObjectMapperreadValue(InputStream in, Class<T> valueType)機能にはクラスが必要です。しかし、内部的に渡しているクラスがデータメンバーとしていくつかのインターフェースを持っている場合、どうすればそれを使用できますか。

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

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)
4

3 に答える 3

63

MetricValueDescriptorJacksonは、インターフェイスであるため、明らかにオブジェクトを構築できません。json と ObjectMapper に追加情報が必要であり、jackson にそれからオブジェクトを構築する方法を伝えます。MVDImplを実装する具象クラスであると仮定して、これを行う 1 つの方法を次に示します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
{
   ...
}

"type":"mvdimpl"json にもフィールドを追加する必要があります。

詳細については公式ドキュメントを参照するつもりでしたが、このトピックをカバーする優れたブログを見つけました - Deserialize JSON with Jackson。このトピックはかなり包括的にカバーされており、例も含まれています。したがって、さらにカスタマイズが必要な場合は、必ずお読みください。

于 2013-10-16T06:15:01.320 に答える
11

私はそれが 2 つの方法のいずれかになると考えていますが、どちらの方法でも、インターフェースを実装する具象クラスを手動で作成する必要があります。

  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

于 2020-09-03T23:37:35.577 に答える