Автор оригинала: 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, поэтому его должно быть легко импортировать и запускать как есть.