Рубрики
Без рубрики

Взгляды Джексона ДЖСОНА

Как использовать аннотацию @JsonView в Джексоне, чтобы идеально контролировать сериализацию ваших объектов (без и с Spring).

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этом уроке мы рассмотрим, как использовать представления Jackson JSON для сериализации/десериализации объектов, настройки представлений и, наконец, как начать интеграцию с Spring.

2. Сериализация С использованием Представлений JSON

Сначала – давайте рассмотрим простой пример – сериализуем объект с помощью @JsonView .

Вот наш взгляд:

public class Views {
    public static class Public {
    }
}

И сущность ” Пользователь “:

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 – каждое из них имеет разные поля, как в следующем примере:

Здесь мы должны посмотреть , где Внутренний расширяется Публичный , а внутренний вид расширяет публичный:

public class Views {
    public static class Public {
    }

    public static class Internal extends Public {
    }
}

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

Обратите внимание, как мы используем reader With View() API для создания Object Reader с использованием данного представления.

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

Далее – давайте посмотрим, как настроить представления JSON. В следующем примере – мы хотим сделать Username ” прописным в результате сериализации.

Мы будем использовать BeanPropertyWriter и BeanSerializerModifier для настройки вашего представления 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 для установки Пользователя имени BeanPropertyWriter с нашим пользовательским прописным писателем :

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"}

И когда мы использовали Внутренний вид следующим образом:

@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, вам следует проверить улучшения Джексона в Spring 4.1 .

7. Заключение

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