1. 概要

このチュートリアルでは、Jackson2.xを使用してオブジェクトをJSONにシリアル化するときに、特定のフィールドを無視する方法を示します。

これは、Jacksonのデフォルトでは不十分で、JSONにシリアル化されるものを正確に制御する必要がある場合に非常に役立ちます。プロパティを無視する方法はいくつかあります。

より深く掘り下げて、ジャクソンでできる他のクールなことを学ぶには、メインのジャクソンチュートリアルに進んでください。

2. クラスレベルでフィールドを無視する

@JsonIgnorePropertiesアノテーションを使用し、名前でフィールドを指定することにより、クラスレベルで特定のフィールドを無視できます。

@JsonIgnoreProperties(value = { "intValue" })
public class MyDto {

    private String stringValue;
    private int intValue;
    private boolean booleanValue;

    public MyDto() {
        super();
    }

    // standard setters and getters are not shown
}

これで、オブジェクトがJSONに書き込まれた後、フィールドが実際に出力の一部ではないことをテストできます。

@Test
public void givenFieldIsIgnoredByName_whenDtoIsSerialized_thenCorrect()
  throws JsonParseException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();
    MyDto dtoObject = new MyDto();

    String dtoAsString = mapper.writeValueAsString(dtoObject);

    assertThat(dtoAsString, not(containsString("intValue")));
}

3. フィールドレベルでフィールドを無視する

フィールドの@JsonIgnoreアノテーションを介して直接フィールドを無視することもできます。

public class MyDto {

    private String stringValue;
    @JsonIgnore
    private int intValue;
    private boolean booleanValue;

    public MyDto() {
        super();
    }

    // standard setters and getters are not shown
}

これで、intValueフィールドが実際にシリアル化されたJSON出力の一部ではないことをテストできます。

@Test
public void givenFieldIsIgnoredDirectly_whenDtoIsSerialized_thenCorrect() 
  throws JsonParseException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();
    MyDto dtoObject = new MyDto();

    String dtoAsString = mapper.writeValueAsString(dtoObject);

    assertThat(dtoAsString, not(containsString("intValue")));
}

4. タイプ別にすべてのフィールドを無視する

最後に、@ JsonIgnoreTypeアノテーションを使用して、指定されたタイプのすべてのフィールドを無視できます。タイプを制御する場合は、クラスに直接アノテーションを付けることができます。

@JsonIgnoreType
public class SomeType { ... }

ただし、多くの場合、クラス自体を制御することはできません。 この場合、ジャクソンミックスインをうまく利用できます。

まず、無視するタイプのMixInを定義し、代わりに@JsonIgnoreTypeで注釈を付けます。

@JsonIgnoreType
public class MyMixInForIgnoreType {}

次に、そのミックスインを登録して、マーシャリング中にすべての String [] タイプを置き換えます(無視します)。

mapper.addMixInAnnotations(String[].class, MyMixInForIgnoreType.class);

この時点で、JSONにマーシャリングされる代わりに、すべての文字列配列が無視されます。

@Test
public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_thenCorrect()
  throws JsonParseException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(String[].class, MyMixInForIgnoreType.class);
    MyDtoWithSpecialField dtoObject = new MyDtoWithSpecialField();
    dtoObject.setBooleanValue(true);

    String dtoAsString = mapper.writeValueAsString(dtoObject);

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
    assertThat(dtoAsString, not(containsString("stringValue")));
}

そして、これが私たちのDTOです:

public class MyDtoWithSpecialField {
    private String[] stringValue;
    private int intValue;
    private boolean booleanValue;
}

注:バージョン2.5以降、このメソッドを使用してプリミティブデータ型を無視することはできないようですが、カスタムデータ型と配列には使用できます。

5. フィルタを使用してフィールドを無視する

最後に、フィルターを使用して、Jacksonの特定のフィールドを無視することもできます。

まず、Javaオブジェクトにフィルターを定義する必要があります。

@JsonFilter("myFilter")
public class MyDtoWithFilter { ... }

次に、intValueフィールドを無視する単純なフィルターを定義します。

SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter
  .serializeAllExcept("intValue");
FilterProvider filters = new SimpleFilterProvider()
  .addFilter("myFilter", theFilter);

これで、オブジェクトをシリアル化して、intValueフィールドがJSON出力に存在しないことを確認できます。

@Test
public final void givenTypeHasFilterThatIgnoresFieldByName_whenDtoIsSerialized_thenCorrect() 
  throws JsonParseException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();
    SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter
      .serializeAllExcept("intValue");
    FilterProvider filters = new SimpleFilterProvider()
      .addFilter("myFilter", theFilter);

    MyDtoWithFilter dtoObject = new MyDtoWithFilter();
    String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);

    assertThat(dtoAsString, not(containsString("intValue")));
    assertThat(dtoAsString, containsString("booleanValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    System.out.println(dtoAsString);
}

6. 結論

この記事では、シリアル化のフィールドを無視する方法について説明しました。 これを最初に名前で行い、次に直接行いました。最後に、MixInsでJavaタイプ全体を無視し、出力をより細かく制御するためにフィルターを使用しました。

これらすべての例とコードスニペットの実装は、GitHubプロジェクトにあります。