2017-08-08 8 views
1

私は巨大なjsonドキュメントとそのjsonにマップされた適切なjasksonモデルを持っています。場合によっては、一部のデータが存在しないため、すべてのオブジェクトで必要なjsonドキュメントを構築することはできません。例えばJackson:nullオブジェクトを空としてシリアル化

私はモデルを次ています

class First { 

    private firstField; 
    private secondField; 
    etc... 
} 

class Second { 

    private firstField; 
    private secondField; 
    etc... 
} 

class General { 

    private First first; 
    private Second second; 
    etc... 
} 

そして最初のインスタンスのみを移入する可能性があります:

{ 
    "first":{ 
     "firstField":"some_value", 
     "secondField":"some_value" 
    }, 
    "second":null 
} 

通常のケースでは、このような何かをシリアライズされますしかし、私の目標は、Generalクラスを次のようにシリアル化することです:

{ 
    "first":{ 
     "firstField":"some_value", 
     "secondField":"some_value" 
    }, 
    "second":{ 
     "firstField":"null", 
     "secondField":"null" 
    } 
} 

デフォルトでは、デフォルトのコンストラクタを使用して、そのメンバーを初期化するために、一般的なクラスを以下のように変更して、これを達成することが可能である:

class General { 

     private First first = new First(); 
     private Second second = new Second() 
     etc... 
    } 

しかし、このアプローチは、既存のモデルの周りにあまりにも多くの変更が発生しますし、私はないですそれが最良のアプローチであることを確かめてください。これを単独で行うカスタムシリアライザを作成することは可能ですか?だから、

、主なアイデアは、インスタンスがnullであり、それがnullの場合、デフォルトを使用して新しいインスタンスを作成することができるはずかどうかを確認することができるだろうシリアライザを作成することです:

https://stackoverflow.com/users/1898563/michael提案に従って編集します注:このシリアライザは、特定のSecondクラスに基づいてはいけません。シンプルな型を除いてシリアライズされるすべてのオブジェクトで動作するはずです。

答えて

2

はい、これを行うためにリフレクションを使用するカスタムシリアライザを作成することは可能です。これを行うには、StdSerializerを追加します。実装は次のようになります。

public class NullSerializer<T> extends StdSerializer<T> { 

    public NullSerializer() { 
     this(null); 
    } 

    public NullSerializer(Class<T> t) { 
     super(t); 
    } 

    @Override 
    public void serialize(T item, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException, 
      IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException) 
    { 

     jgen.writeStartObject(); 

     // For all fields of the class you're serializing 
     for (final Field field : item.getClass().getDeclaredFields()) 
     { 
      field.setAccessible(true); 

      Object value = field.get(item); 

      // if the value is null, create a new instance 
      if (value == null) 
      { 
       value = field.getType().getConstructor().newInstance(); 
      } 

      // write it 
      jgen.writeObject(value); 
     } 

     jgen.writeEndObject(); 
    } 
} 

これは、各フィールドに共通のデフォルトのコンストラクタがあることに依存しています。私が行ったように、署名にスローされたものとしてそれらを宣言するのではなく、例外のいくつかをキャッチしたいかもしれません。

このシリアライザをObjectMapperに登録する必要があります。 This articleでその方法を説明しています。


これは特に優雅な解決策ではないと思いますが、要件を満たす必要があります。私は最初にnull可能なフィールドを持つことを避けるだろうが、多分あなたのケースでは可能ではない。

+0

おかげさまで、おそらく私の質問は適切な方法で記述されていませんでした。シンプルタイプ以外のオブジェクトをチェックできるシリアライザを実際に持っている主なアイデアです。デフォルトのコンストラクタを使って新しいオブジェクトを作成することができるので、特定の第2の型に基づいてはならず、直列化される各新しいオブジェクトを扱うことができるはずです。 – fashuser

+0

問題ありません。それではあなたの質問を編集する必要があります。 – Michael

+0

完了、あなたが提案したように更新 – fashuser

関連する問題