Джексон JSON Просмотров

Джексон JSON Просмотров

1. обзор

В этом руководстве мы рассмотрим, как использовать представления Jackson JSON Views для сериализации / десериализации объектов, настройки представлений и, наконец, как начать интеграцию со 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, каждое из которых имеет разные поля, как в следующем примере:

Здесь нам нужно просмотреть, гдеInternal расширяетPublic, а внутреннее представление расширяет общедоступное:

public class Views {
    public static class Public {
    }

    public static class Internal extends Public {
    }
}

А вот наша сущность «Item», где в представлениеPublic включены только поляid иname:

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 для сериализации - толькоid иname будут сериализованы в 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 Views для десериализации объектов, в частности экземпляра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());
}

Обратите внимание, как мы используем APIreaderWithView() для созданияObjectReader с использованием данного представления.

5. Настроить представления JSON

Далее - давайте посмотрим, как настроить представления JSON. В следующем примере мы хотим сделатьUser «name» верхним регистром в результате сериализации.

Мы будем использоватьBeanPropertyWriter иBeanSerializerModifier для настройки нашего представления JSON. Во-первых - вотBeanPropertyWriterUpperCasingWriter для преобразованияUsername в верхний регистр:

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 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. Использование представлений JSON с Spring

Наконец, давайте кратко рассмотрим использование представлений JSON сSpring Framework. Мы можем использовать аннотацию@JsonView для настройки нашего ответа JSON на уровне API.

В следующем примере мы использовали представление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. Заключение

В этом быстром уроке мы взглянули на JSON-представления Джексона и аннотацию @JsonView. Мы показали, как использовать JSON Views, чтобы получить детальный контроль над процессом сериализации / десериализации - используя одно или несколько представлений.