Автор оригинала: Eugen Paraschiv.
1. Обзор
В этом кратком руководстве мы проанализируем сортировку сущностей без геттеров и решение для исключения Jackson JsonMappingException exception .
Если вы хотите копнуть глубже и узнать другие интересные вещи, которые вы можете сделать с помощью Jackson 2 – перейдите к основному учебнику Джексона .
Дальнейшее чтение:
Вступление к объектному изображению Джексона
Использование опционально с Джексоном
Spring JSON-P с Джексоном
2. Проблема
По умолчанию Jackson 2 будет работать только с полями, которые либо являются общедоступными, либо имеют методы общедоступного геттера – сериализация сущности, у которой все поля являются закрытыми или пакет закрыт, завершится неудачей :
public class MyDtoNoAccessors {
String stringValue;
int intValue;
boolean booleanValue;
public MyDtoNoAccessors() {
super();
}
// no getters
}@Test(expected = JsonMappingException.class)
public void givenObjectHasNoAccessors_whenSerializing_thenException()
throws JsonParseException, IOException {
String dtoAsString = new ObjectMapper().writeValueAsString(new MyDtoNoAccessors());
assertThat(dtoAsString, notNullValue());
}полное исключение :
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class dtos.MyDtoNoAccessors and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )
3. Решение
Очевидным решением является добавление геттеров для полей – если объект находится под нашим контролем. Если это не так и изменение источника сущности невозможно – тогда Джексон предоставляет нам несколько альтернатив.
3.1. Глобальное Автоматическое Обнаружение Полей С Любой Видимостью
Первым решением этой проблемы является глобальная настройка ObjectMapper для обнаружения всех полей, независимо от их видимости:
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Это позволит обнаруживать поля private и package private без геттеров, и сериализация будет работать правильно:
@Test
public void givenObjectHasNoAccessors_whenSerializingWithAllFieldsDetected_thenNoException()
throws JsonParseException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());
assertThat(dtoAsString, containsString("intValue"));
assertThat(dtoAsString, containsString("stringValue"));
assertThat(dtoAsString, containsString("booleanValue"));
}3.2. Обнаружены все поля на уровне класса
Другой вариант, который предоставляет Джексон 2, – это – вместо глобальной конфигурации – управление видимостью поля на уровне класса с помощью @JsonAutoDetect аннотации:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }С помощью этой аннотации сериализация теперь должна корректно работать с этим конкретным классом:
@Test
public void givenObjectHasNoAccessorsButHasVisibleFields_whenSerializing_thenNoException()
throws JsonParseException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());
assertThat(dtoAsString, containsString("intValue"));
assertThat(dtoAsString, containsString("stringValue"));
assertThat(dtoAsString, containsString("booleanValue"));
}4. Заключение
В этой статье показано , как обойти видимость поля по умолчанию в Jackson , настроив пользовательскую видимость либо глобально на ObjectMapper , либо на отдельных классах. Джексон позволяет еще больше настраивать, предоставляя опции для точного управления тем, как картограф видит геттеры, сеттеры или поля с определенной видимостью.
Реализацию всех этих примеров и фрагментов кода можно найти в моем проекте GitHub – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.