ジャクソンJSONビュー

ジャクソンJSONビュー

1. 概要

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

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

最初に–簡単な例–serialize an object with @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")));
}

特定のビューをアクティブにしてシリアル化しているため、only the right fields being serializedが表示されていることに注意してください。

また、デフォルトでは、ビューの一部として明示的にマークされていないすべてのプロパティがシリアル化されていることを理解することも重要です。 便利な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ビューをカスタマイズする方法を見てみましょう。 次の例では、シリアル化の結果でUsername”を大文字にします。

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

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で、Userの名前BeanPropertyWriterをカスタムUpperCasingWriterで設定します。

public class MyBeanSerializerModifier extends BeanSerializerModifier{

    @Override
    public List changeProperties(
      SerializationConfig config, BeanDescription beanDesc,
      List 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ビューの使用

最後に、Spring Frameworkで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でのビューの使用についてさらに詳しく知りたい場合は、the Jackson improvements in Spring 4.1を確認する必要があります。

7. 結論

このクイックチュートリアルでは、Jackson JSONビューと@JsonViewアノテーションを確認しました。 JSONビューを使用して、単一または複数のビューを使用して、シリアライズ/デシリアライズプロセスをきめ細かく制御する方法を示しました。