Перейти к основному содержимому

Джексон — JsonMappingException (сериализатор для класса не найден)

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы проанализируем маршаллинг сущностей без геттеров и решение для исключения Jackson JsonMappingException .

Если вы хотите копнуть глубже и узнать о других интересных вещах, которые вы можете делать с Jackson 2, — перейдите к основному руководству по Jackson .

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

Это позволит обнаруживать приватные и приватные поля пакета без геттеров, и сериализация будет работать корректно:

@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. Обнаружены все поля на уровне класса

Другой вариант, предоставляемый Jackson 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, поэтому его легко импортировать и запускать как есть.