Этот учебник проиллюстрирует, как мы можем использовать Джексона для сериализации поля только в том случае, если оно соответствует определенным пользовательским критериям .
Например, предположим, что мы хотим сериализовать целочисленное значение только в том случае, если оно положительное, и мы хотим полностью пропустить его, если это не так.
Если вы хотите копнуть глубже и узнать другие интересные вещи, которые вы можете сделать с помощью Jackson 2 – перейдите к основному учебнику Джексона .
2. Используйте фильтр Джексона для управления процессом сериализации
Во-первых, нам нужно определить фильтр для нашей сущности, используя аннотацию @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;
}
}
Затем нам нужно определить наш пользовательский Фильтр свойств :
PropertyFilter theFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!writer.getName().equals("intValue")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
int intValue = ((MyDtoWithFilter) pojo).getIntValue();
if (intValue >= 0) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
Этот фильтр содержит фактическую логику , определяющую, будет ли поле intValue сериализовано или нет , на основе его значения.
Затем мы подключаем этот фильтр в ObjectMapper и сериализуем объект:
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", theFilter);
MyDto dtoObject = new MyDto();
dtoObject.setIntValue(-1);
ObjectMapper mapper = new ObjectMapper();
String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);
И, наконец, мы можем проверить, что поле int Value действительно не является частью маршалированного вывода JSON :
Теперь – давайте обсудим, как пропустить объекты при сериализации на основе свойства value . Мы пропустим все объекты, где свойство скрыто является истинным :
3.1. Скрытые классы
Во-первых, давайте взглянем на наш Hidable Интерфейс:
@JsonIgnoreProperties("hidden")
public interface Hidable {
boolean isHidden();
}
И у нас есть два простых класса, реализующих этот интерфейс Person , Address :
Человек Класс:
public class Person implements Hidable {
private String name;
private Address address;
private boolean hidden;
}
И Адрес Класс:
public class Address implements Hidable {
private String city;
private String country;
private boolean hidden;
}
Примечание: Мы использовали @JsonIgnoreProperties(“hidden”) , чтобы убедиться, что hidden само свойство не включено в JSON
3.2. Пользовательский сериализатор
Далее – вот наш пользовательский сериализатор:
public class HidableSerializer extends JsonSerializer {
private JsonSerializer
Обратите внимание, что:
Когда объект не будет пропущен, мы делегируем сериализацию введенному по умолчанию сериализатору.
Мы переопределили метод isEmpty() – чтобы убедиться, что в случае, если скрытый объект является свойством, имя свойства также исключается из JSON.
3.3. Использование BeanSerializerModifier
Наконец, нам нужно будет использовать BeanSerializerModifier для введения сериализатора по умолчанию в наш пользовательский HidableSerializer – следующим образом:
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. Пример вывода
Вот простой пример сериализации:
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"));
}
Далее, скрыт только адрес :
@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"));
}
Теперь весь человек скрыт :
@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. Заключение
Этот тип расширенной фильтрации невероятно мощен и позволяет очень гибко настраивать json при сериализации сложных объектов с помощью Jackson.
Более гибкой, но и более сложной альтернативой было бы использование полностью настраиваемого сериализатора для управления выводом JSON – поэтому, если это решение недостаточно гибкое, возможно, стоит изучить это.
Реализация всех этих примеров и фрагментов кода может быть найденана GitHub – это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.