2017-01-09 4 views
1

例えば、以下のように定義されたPOJOは、jackson-corejackson-databind(バージョン2.8.3)の注釈で簡潔に省略されています。Jacksonフィールドのカスタム動作のためのカスタムシリアライザ

class Sample { 
    private String foo; 
    private String bar; 
    private Map<String, Map<String, Object>> data; 
} 

と私はPOJOの上にかかり、(

{ 
    "foo":"val", 
    "bar":"val2", 
    "data_1": { 
      "someInt":1 
    }, 
    "data_2": { 
      "someBoolean":true 
    } 
} 

ここdata_1data_2がメインMapの鍵で生成され、その内側の属性は、そのサブマップから構成されているカスタム・シリアライザを書きたいですネストされたマップ)。また、結果のJSONには実際のプロパティデータが存在してはいけません。

fooとbarはフィールドの例ですが、実際にはpojoには15以上のフィールドがあります。

答えて

0

私はカスタム・シリアライザを使用せずにこれを行うための簡単な方法を考え出しました。それは@JsonAnyGetterと@JsonAnySetterで行われました。ここに完全な例があります。他の人にとって役に立ちそうなので、ここに貼り付けられたサンプルに関する回答を貼り付けています。

class Sample { 
    private String foo; 
    private String bar; 

    private Map<String, Map<String, Object>> data = new LinkedHashMap<>(); 

    @JsonAnyGetter 
    public Map<String, Map<String, Object>> getData() { 
      return data; 
    } 

    @JsonAnySetter 
    public void set(String key, Map<String, Object>) { 
      data.put(key, object); 
    } 
} 

Example

0

それは、こののようにシリアル化する方法を記述し、この

private Map<String,Map<String, Object>> data; 

ようにする必要があり、変数データ、 をあなたのクラスを修正してください:私が思うに、これは正常に動作する必要があり

public static void serializeSample() { 
    ObjectMapper mapper = new ObjectMapper(); 
    Sample sample=new Sample(); 
    sample.setBar("val2"); 
    sample.setFoo("val"); 
    Map<String, Map<String, Object>> sampleData=new HashMap<>(); 
    Map<String, Object> data_3=new HashMap<>(); 
    Map<String, Object> data_4=new HashMap<>(); 
    data_3.put("someInt", 1); 
    data_4.put("someBoolean", Boolean.TRUE); 

    sampleData.put("data_1", data_3); 
    sampleData.put("data_2", data_4); 
    sample.setData(sampleData); 

    try { 
     mapper.writeValue(new File("log.txt"), sample); 
    } catch (JsonGenerationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (JsonMappingException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 



} 

+0

申し訳ありませんが、私はこのために静的メソッドを使用することはできません、POJOは春での浮きと、ばねのデータでのNoSQLストアに移行します。 –

0

カスタムシリアライザが必要ですで、それは親よりも反復されますMap。入れ子になった各Mapについては、writeObjectFieldとkey、valueをフィールド名と値として単純に使用できます。

また、その他のフィールドはすべて自動的にシリアル化される必要があります。フィールドにのみカスタムシリアライザを設定できますが、JSONにはまだdataというフィールドがあります。実際には、データの内容を昇順にして、フィールドがSampleのように見え、それにはSampleのカスタムシリアライザが必要です。私は自動的にdataフィールドを除く他のすべてをシリアル化するために考えることができる唯一の方法は、以下のシリアライザは、あなたの質問のようにJSONを生成します反射

を使用することです:

class SampleSerializer extends StdSerializer<Sample> { 
    private static final List<Field> sampleFields; 

    public SampleSerializer() { this(null); } 
    private SampleSerializer(Class<Sample> t) { super(t); } 

    static { 
     sampleFields = Arrays.stream(Sample.class.getDeclaredFields()) 
       .filter(f -> !("data".equals(f.getName()))) 
       .collect(toList()); 
    } 

    @Override 
    public void serialize(Sample sample, JsonGenerator jgen, SerializerProvider provider) throws IOException { 
     jgen.writeStartObject(); 
     for (Field field : sampleFields) { 
      try { 
       field.setAccessible(true); 
       jgen.writeObjectField(field.getName(), field.get(sample)); 
      } catch (IllegalAccessException ignored) { 
      } 
     } 
     for (Entry<String, Map<String, Object>> entry : sample.getData().entrySet()) { 
      jgen.writeObjectField(entry.getKey(), entry.getValue()); 
     } 
     jgen.writeEndObject(); 
    } 
} 

またSampleSerializerがされるように指定する必要がありますクラスに注釈を付けることにより、例えば、Sampleに使用:

@JsonSerialize(using = SampleSerializer.class) 
class Sample { 
+0

これは私が欲しいものです。しかし、2つのステートメント 'jgen.writeStringField(" foo "、sample.getFoo()); jgen.writeStringField( "bar"、sample。'' 012B は、他の多くの複雑なフィールドを持つ非常に複雑なpojoになるため、望ましくありません。私はjacksonに何か言いたいのですが、注釈に従ってfooとbarフィールドをシリアル化し、データフィールドの振る舞いを指定させてください。 –

+0

私はリフレクションを*自動的に*シリアル化し、*手動で*シリアル化します。それは動作しますが、それはかなり見えません。 –

関連する問題