1. 概要

このチュートリアルでは、Jackson JSONビューを使用してオブジェクトをシリアル化/逆シリアル化する方法、ビューをカスタマイズする方法、そして最後にSpringとの統合を開始する方法について説明します。

2. JSONビューを使用してシリアル化

最初に–簡単な例を見てみましょう–@JsonViewでオブジェクトをシリアル化します。

これが私たちの見解です:

public class Views {
    public static class Public {
    }
}

そして、「 User 」エンティティ:

public class User {
    public int id;

    @JsonView(Views.Public.class)
    public String name;
}

次に、ビューを使用して「User」インスタンスをシリアル化します。

@Test
public void whenUseJsonViewToSerialize_thenCorrect() 
  throws JsonProcessingException {
 
    User user = new User(1, "John");

    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);

    String result = mapper
      .writerWithView(Views.Public.class)
      .writeValueAsString(user);

    assertThat(result, containsString("John"));
    assertThat(result, not(containsString("1")));
}

特定のビューをアクティブにしてシリアル化しているため、正しいフィールドのみがシリアル化されていることが表示されていることに注意してください。

また、デフォルトでは、ビューの一部として明示的にマークされていないすべてのプロパティがシリアル化されることを理解することも重要です。 便利なDEFAULT_VIEW_INCLUSION機能を使用して、この動作を無効にしています。

3. 複数のJSONビューを使用する

次へ–複数のJSONビューの使用方法を見てみましょう–次の例のように、それぞれに異なるフィールドがあります。

ここでは、InternalPublicを拡張し、内部ビューがパブリックビューを拡張するビューを表示する必要があります。

public class Views {
    public static class Public {
    }

    public static class Internal extends Public {
    }
}

そして、これが私たちのエンティティ「 Item 」で、フィールドidnameのみがPublicビューに含まれています。

public class Item {
 
    @JsonView(Views.Public.class)
    public int id;

    @JsonView(Views.Public.class)
    public String itemName;

    @JsonView(Views.Internal.class)
    public String ownerName;
}

Public ビューを使用してシリアル化する場合、idnameのみがJSONにシリアル化されます。

@Test
public void whenUsePublicView_thenOnlyPublicSerialized() 
  throws JsonProcessingException {
 
    Item item = new Item(2, "book", "John");

    ObjectMapper mapper = new ObjectMapper();
    String result = mapper
      .writerWithView(Views.Public.class)
      .writeValueAsString(item);

    assertThat(result, containsString("book"));
    assertThat(result, containsString("2"));

    assertThat(result, not(containsString("John")));
}

ただし、 Internal ビューを使用してシリアル化を実行すると、すべてのフィールドがJSON出力の一部になります。

@Test
public void whenUseInternalView_thenAllSerialized() 
  throws JsonProcessingException {
 
    Item item = new Item(2, "book", "John");

    ObjectMapper mapper = new ObjectMapper();
    String result = mapper
      .writerWithView(Views.Internal.class)
      .writeValueAsString(item);

    assertThat(result, containsString("book"));
    assertThat(result, containsString("2"));

    assertThat(result, containsString("John"));
}

4. JSONビューを使用した逆シリアル化

次に、JSONビューを使用してオブジェクトを逆シリアル化する方法を見てみましょう。具体的には、Userインスタンスです。

@Test
public void whenUseJsonViewToDeserialize_thenCorrect() 
  throws IOException {
    String json = "{"id":1,"name":"John"}";

    ObjectMapper mapper = new ObjectMapper();
    User user = mapper
      .readerWithView(Views.Public.class)
      .forType(User.class)
      .readValue(json);

    assertEquals(1, user.getId());
    assertEquals("John", user.getName());
}

readerWithView() APIを使用して、指定されたビューを使用してObjectReaderを作成していることに注意してください。

5. JSONビューをカスタマイズする

次へ–JSONビューをカスタマイズする方法を見てみましょう。 次の例では、シリアル化の結果で User name ”UpperCaseを作成します。

BeanPropertyWriterBeanSerializerModifierを使用して、JSONビューをカスタマイズします。 まず、 BeanPropertyWriter UpperCasingWriter を使用して、 User nameを大文字に変換します。

public class UpperCasingWriter extends BeanPropertyWriter {
    BeanPropertyWriter _writer;

    public UpperCasingWriter(BeanPropertyWriter w) {
        super(w);
        _writer = w;
    }

    @Override
    public void serializeAsField(Object bean, JsonGenerator gen, 
      SerializerProvider prov) throws Exception {
        String value = ((User) bean).name;
        value = (value == null) ? "" : value.toUpperCase();
        gen.writeStringField("name", value);
    }
}

そして、これが BeanSerializerModifier で、UserBeanPropertyWriterをカスタムUpperCasingWriterで設定します。

public class MyBeanSerializerModifier extends BeanSerializerModifier{

    @Override
    public List<BeanPropertyWriter> changeProperties(
      SerializationConfig config, BeanDescription beanDesc, 
      List<BeanPropertyWriter> beanProperties) {
        for (int i = 0; i < beanProperties.size(); i++) {
            BeanPropertyWriter writer = beanProperties.get(i);
            if (writer.getName() == "name") {
                beanProperties.set(i, new UpperCasingWriter(writer));
            }
        }
        return beanProperties;
    }
}

次に、変更したシリアライザーを使用して、Userインスタンスをシリアル化します。

@Test
public void whenUseCustomJsonViewToSerialize_thenCorrect() 
  throws JsonProcessingException {
    User user = new User(1, "John");
    SerializerFactory serializerFactory = BeanSerializerFactory.instance
      .withSerializerModifier(new MyBeanSerializerModifier());

    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializerFactory(serializerFactory);

    String result = mapper
      .writerWithView(Views.Public.class)
      .writeValueAsString(user);

    assertThat(result, containsString("JOHN"));
    assertThat(result, containsString("1"));
}

6. SpringでのJSONビューの使用

最後に、 SpringFrameworkでJSONビューを使用する方法を簡単に見てみましょう。 @JsonView アノテーションを利用して、APIレベルでJSON応答をカスタマイズできます。

次の例では、Publicビューを使用して応答しました。

@JsonView(Views.Public.class)
@RequestMapping("/items/{id}")
public Item getItemPublic(@PathVariable int id) {
    return ItemManager.getById(id);
}

応答は次のとおりです。

{"id":2,"itemName":"book"}

また、 Internalビューを次のように使用した場合:

@JsonView(Views.Internal.class)
@RequestMapping("/items/internal/{id}")
public Item getItemInternal(@PathVariable int id) {
    return ItemManager.getById(id);
}

それが応答でした:

{"id":2,"itemName":"book","ownerName":"John"}

Spring 4.1でのビューの使用についてさらに詳しく知りたい場合は、 Spring4.1でのJacksonの改善点を確認する必要があります。

7. 結論

このクイックチュートリアルでは、JacksonJSONビューと@JsonViewアノテーションを確認しました。 JSONビューを使用して、単一または複数のビューを使用して、シリアル化/逆シリアル化プロセスをきめ細かく制御する方法を示しました。 このチュートリアルの完全なコードは、GitHubにあります。