2017-08-08 22 views
1

I'va多くの具体的なタイプで実現することができるOIDインタフェース:ジャクソンの多型シリアライズ/デシリアライゼーションのカスタムシリアライザ/デシリアライザ

public interface OID { 
} 
public abstract class OIDBase 
      implements OID { 
    private String _id; 
} 
public class MyOID 
    extends OIDBase { 
    public MyOID() { 
     // default no-args constructor 
    } 
} 
public class MyOtherOID 
    extends OIDBase { 
    public MyOtherOID() { 
     // default no-args constructor 
    } 
} 

今、私は2つのフィールドを持つオブジェクトをした、1抽象を使用して定義インターフェイスタイプ(OID)と他のコンクリートの種類(筋様)を使用して定義

public class MyBean { 
    private OID _absOid; 
    private MyOID _concreteOid; 

    public MyBean(final OID absOid,final MyOID concreteOid) { 
     _absOid = absOid; 
     _concreteOid = concreteOid; 
    } 
} 

私は抽象インタフェース型やコンクリート型を使用して、それらが定義されているかどうかを、異なるフィールドをデシリアライズ/シリアライズするジャクソンを使用します:

{ 
    "_absOid": { 
        "type" : "MyOtherOID", 
        "id" : "__an_id__" 
       }, 
    "_concreteOid" : "__another_id___" 
} 

_absOidは型情報(多型シリアライズ)と_concreteOidなどのシリアル化されていることに注意してくださいそうするために、テキスト

としてシリアル化されて、私はとOIDインタフェースを注釈を付けました:

@JsonSubTypes({ 
    @JsonSubTypes.Type(MyOID.class), 
    @JsonSubTypes.Type(MyOtherOID.class) 
}) 
public interface OID { 
} 

と割り当て各コンクリートタイプのタイプID:

@JsonTypeName("MyOID") 
public class MyOID 
    extends OIDBase { 
    ... 
} 
@JsonTypeName("MyOtherOID") 
public class MyOtherOID 
    extends OIDBase { 
    ... 
} 

public class MyBean { 
    @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, 
        use = JsonTypeInfo.Id.NAME, 
        property = "type") 
    private OID _absOid; 

    private MyOID _concreteOid; 
} 

これまでのところ、とても良いが、フィールドは抽象型(OIDを使用して定義されている場合、異なるシリアル化するために:最後に、コンテナ豆の抽象的な定義フィールドは、ジャクソンは型情報を含める作るために注釈を付けています)とフィールドは、具体的なタイプ(筋様)を使用して定義されている場合、私は、カスタム・シリアライザを作成する必要があります。

まずシリアライザ/デシリアライザを使用するために、具体的なタイプに注釈を付ける:

@JsonTypeName("MyOID") 
@JsonSerialize(using=OIDSerializer.class) @JsonDeserialize(using=OIDDeSerializer.class) 
public class MyOID 
    extends OIDBase { 
    ... 
} 
@JsonTypeName("MyOtherOID") 
@JsonSerialize(using=OIDSerializer.class) @JsonDeserialize(using=OIDDeSerializer.class) 
public class MyOtherOID 
    extends OIDBase { 
    ... 
} 

...シリアライザ/デシリアライザコード:

public static class OIDSerializer 
      extends JsonSerializer<OID> { 
    @Override 
    public void serialize(final OID value, 
          final JsonGenerator jgen, 
          final SerializerProvider provider) throws IOException,JsonProcessingException { 
     // **** used when serializing a concrete type 
     jgen.writeString(value.toString()); 
    } 
    @Override 
    public void serializeWithType(final OID value, 
            final JsonGenerator jgen, 
            final SerializerProvider provider, 
            final TypeSerializer typeSer) throws IOException { 
     // **** used when serializing a polymorphic type 
     // guess the type id 
     WritableTypeId typeId = typeSer.typeId(value,JsonToken.START_OBJECT); 

     // type prefix 
     typeSer.writeTypePrefix(jgen, 
           typeId); 

     // object 
     jgen.writeFieldName("id"); 
     jgen.writeString(value.toString()); 

     // type suffix 
     typeId.wrapperWritten = !jgen.canWriteTypeId(); 
     typeSer.writeTypeSuffix(jgen, 
           typeId); 
    } 
} 

デシリアライズするときPROBLEMは JSON文字列をを発生し、私は次のカスタムデシリアライザを使用しました:

public static class OIDDeSerializer 
      extends StdDeserializer<OID> { 

    public MyOIDDeSerializer() { 
     super(MyOID.class); 
    } 
    @Override 
    public OID deserialize(final JsonParser jp, 
          final DeserializationContext ctxt) throws IOException,JsonProcessingException {    
     JsonNode node = jp.getCodec().readTree(jp); 

     // [1] - Read the id depending on the serialized format 
     String oidStr = null;   
     // text node > concrete oid impl serialized as [value] 
     if (node.getNodeType() == JsonNodeType.STRING) { 
      oidStr = ((TextNode)node).asText(); 
     } 
     // oid=value > abstract oid impl serialized as {typeId=[type],oid={value]} 
     else { 
      ObjectNode objNode = (ObjectNode)node; 
      oidStr = objNode.findValue("id").asText(); 
     } 

     // [2] - Read tye type id 
     String typeId = objNode.findValue("type").asText() 

     // PROBLEM!!!!!! 
     // how get the type from the typeId in order to create the concrete instance 
     // how access the type resolver???? 
     Class<? extends OID> oidType = RESOLVE TYPE FROM THE ID 
     return oidType.newInstance(); 
    } 
} 

ので問題は、型にアクセスする方法をですタイプID解決からカスタムデシリアライザ ???

+0

私はジャクソンには専門家だが、私はおそらく、次のいずれかを試してみた:1.試しOID' '上の注釈を読んで、id型に一致する注釈からクラスを取得するか、2 。型IDを使用する代わりに、完全修飾クラス名を使用しようとしていました。シリアライズすると、単純な 'Cl ass.forName(fqcn) '。 - おそらく、あなたはあなた自身で注釈をスキャンすることなく、変種1をやる方法を探していますか? – Thomas

+0

ありがとう@トーマス、ソリューションに問題があります。問題はアノテーションにアクセスする方法です。info:sachinが指摘しているように、Jacksonは注釈イントロスペクターを使用しています。 – futuretelematics

答えて

関連する問題