Visualizações JSON de Jackson

Visualizações JSON de Jackson

1. Visão geral

Neste tutorial, veremos como usar Jackson JSON Views para serializar / desserializar objetos, personalizar as visualizações e, finalmente, como começar a integração com Spring.

2. Serializar usando visualizações JSON

Primeiro - vamos ver um exemplo simples -serialize an object with @JsonView.

Aqui está a nossa visão:

public class Views {
    public static class Public {
    }
}

E a entidade “User”:

public class User {
    public int id;

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

Agora vamos serializar uma instância “User” usando nossa visão:

@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")));
}

Observe como, porque estamos serializando com uma vista específica ativa, estamos vendoonly the right fields being serialized.

Também é importante entender que - por padrão - todas as propriedades não marcadas explicitamente como parte de uma visualização são serializadas. Estamos desativando esse comportamento com o útil recursoDEFAULT_VIEW_INCLUSION.

3. Use várias visualizações JSON

A seguir - vamos ver como usar várias visualizações JSON - cada uma tem campos diferentes, como no exemplo a seguir:

Aqui temos as visualizações ondeInternal estendePublic, com a visualização interna estendendo a pública:

public class Views {
    public static class Public {
    }

    public static class Internal extends Public {
    }
}

E aqui está nossa entidade “Item”, onde apenas os camposidename estão incluídos na visualizaçãoPublic:

public class Item {

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

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

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

Se usarmos a visualizaçãoPublic para serializar - apenasidename serão serializados para 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")));
}

Mas se usarmos a visualizaçãoInternal para realizar a serialização, todos os campos farão parte da saída 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. Desserializar usando visualizações JSON

Agora - vamos ver como usar visualizações JSON para desserializar objetos - especificamente, uma instânciaUser:

@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());
}

Observe como estamos usando a APIreaderWithView() para criar umObjectReader usando a visualização fornecida.

5. Personalizar visualizações JSON

A seguir - vamos ver como personalizar visualizações JSON. No próximo exemplo - queremos fazerUsername” UpperCase no resultado da serialização.

UsaremosBeanPropertyWritereBeanSerializerModifier para personalizar nossa visualização JSON. Primeiro - aqui está oBeanPropertyWriterUpperCasingWriter para transformarUsername em maiúsculas:

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);
    }
}

E aqui está oBeanSerializerModifier para definir o nomeUserBeanPropertyWriter com nossoUpperCasingWriter personalizado:

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

Agora - vamos serializar uma instânciaUser usando o Serializer modificado:

@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. Usando visualizações JSON com Spring

Finalmente - vamos dar uma olhada rápida no uso de visualizações JSON comSpring Framework. Podemos aproveitar a anotação@JsonView para personalizar nossa resposta JSON no nível da API.

No exemplo a seguir - usamos a visualizaçãoPublic para responder:

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

A resposta é:

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

E quando usamos a visualizaçãoInternal da seguinte maneira:

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

Essa foi a resposta:

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

Se você quiser se aprofundar no uso das visualizações com Spring 4.1, você deve verificarthe Jackson improvements in Spring 4.1.

7. Conclusão

Neste tutorial rápido, vimos as visualizações Jackson JSON e a anotação @JsonView. Mostramos como usar as visualizações JSON para ter um controle refinado sobre nosso processo de serialização / desserialização - usando uma ou várias visualizações.