Serialize apenas campos que atendem a um critério personalizado com Jackson
1. Visão geral
Este tutorial vai ilustrar como podemosuse Jackson to only serialize a field if it meets a specific, custom criteria.
Por exemplo, digamos que queremos serializar um valor inteiro apenas se for positivo - e queremos ignorá-lo totalmente se não for.
Se você quiser se aprofundar e aprenderother cool things you can do with the Jackson 2, vá parathe main Jackson tutorial.
2. Use o filtro Jackson para controlar o processo de serialização
Primeiro, precisamos definir o filtro em nossa entidade, usando a anotação@JsonFilter:
@JsonFilter("myFilter")
public class MyDto {
private int intValue;
public MyDto() {
super();
}
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
}
Agora - vamos discutir como pular objetos durante a serialização com base na propriedadevalue. Vamos pular todos os objetos onde a propriedadehidden étrue:
3.1. Classes Hidable
Primeiro, vamos dar uma olhada em nossa interfaceHidable:
@JsonIgnoreProperties("hidden")
public interface Hidable {
boolean isHidden();
}
E temos duas classes simples implementando esta interfacePerson,Address:
ClassePerson:
public class Person implements Hidable {
private String name;
private Address address;
private boolean hidden;
}
E classeAddress:
public class Address implements Hidable {
private String city;
private String country;
private boolean hidden;
}
Observação: usamos@JsonIgnoreProperties(“hidden”) para garantir que a propriedadehidden em si não esteja incluída em JSON
3.2. Serializador Personalizado
Em seguida - aqui está o nosso serializador personalizado:
public class HidableSerializer extends JsonSerializer {
private JsonSerializer
Observe que:
Quando o objeto não será ignorado, delegamos a serialização ao serializador injetado padrão.
Substituímos o métodoisEmpty() - para garantir que, no caso de objeto Hidable ser uma propriedade, o nome da propriedade também será excluído do JSON.
3.3. UsandoBeanSerializerModifier
Finalmente, precisaremos usarBeanSerializerModifier para injetar o serializador padrão em nossoHidableSerializer personalizado - da seguinte forma:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_EMPTY);
mapper.registerModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer> modifySerializer(
SerializationConfig config, BeanDescription desc, JsonSerializer> serializer) {
if (Hidable.class.isAssignableFrom(desc.getBeanClass())) {
return new HidableSerializer((JsonSerializer) serializer);
}
return serializer;
}
});
}
});
3.4. Saída de amostra
Aqui está um exemplo simples de serialização:
Address ad1 = new Address("tokyo", "jp", true);
Address ad2 = new Address("london", "uk", false);
Address ad3 = new Address("ny", "usa", false);
Person p1 = new Person("john", ad1, false);
Person p2 = new Person("tom", ad2, true);
Person p3 = new Person("adam", ad3, false);
System.out.println(mapper.writeValueAsString(Arrays.asList(p1, p2, p3)));
@Test
public void whenNotHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", false);
Person person = new Person("john", ad, false);
String result = mapper.writeValueAsString(person);
assertTrue(result.contains("name"));
assertTrue(result.contains("john"));
assertTrue(result.contains("address"));
assertTrue(result.contains("usa"));
}
A seguir,only address is hidden:
@Test
public void whenAddressHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", true);
Person person = new Person("john", ad, false);
String result = mapper.writeValueAsString(person);
assertTrue(result.contains("name"));
assertTrue(result.contains("john"));
assertFalse(result.contains("address"));
assertFalse(result.contains("usa"));
}
Agora,entire person is hidden:
@Test
public void whenAllHidden_thenCorrect() throws JsonProcessingException {
Address ad = new Address("ny", "usa", false);
Person person = new Person("john", ad, true);
String result = mapper.writeValueAsString(person);
assertTrue(result.length() == 0);
}
4. Conclusão
Esse tipo de filtragem avançada é incrivelmente poderoso e permite uma personalização muito flexível do json ao serializar objetos complexos com Jackson.
Uma alternativa mais flexível, mas também mais complexa, seria usar um serializador totalmente personalizado para controlar a saída JSON - então, se esta solução não for flexível o suficiente, pode valer a pena dar uma olhada nisso.
A implementação de todos esses exemplos e fragmentos de códigocan be found in my github project - este é um projeto baseado no Eclipse, portanto, deve ser fácil de importar e executar como está.