Найти тему

Jackson – JsonMappingException (сериализатор для класса не найден)

Оглавление

1. Обзор

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

2. Проблема

По умолчанию Jackson 2 будет работать только с полями, которые либо являются общедоступными, либо имеют общедоступные методы получения – сериализация объекта, у которого все поля являются частными, или package private завершится неудачей:

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

Другой вариант, который предоставляет 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. Отключите fail_on_empty_beans в Jackson

В Jackson функция fail_on_empty_beans определяет, следует ли генерировать исключение, если сериализуемый объект пуст (не имеет свойств). По умолчанию Jackson генерирует исключение, если он обнаруживает пустой компонент во время сериализации.

Стоит отметить, что функция fail_on_empty_beans включена по умолчанию, поэтому, если мы хотим отключить ее, нам нужно явно установить для нее значение false. Для этого мы можем использовать два подхода в зависимости от нашего конкретного варианта использования.

4.1. Использование конфигурации Object Mapper

Мы можем отключить fail_on_empty_beans, используя ObjectMapper напрямую:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Настраивая ObjectMapper таким образом, мы сообщаем Джексону, чтобы он не генерировал исключение при обнаружении пустого компонента во время процесса сериализации.

4.2. Использование пружинного ботинка

В Spring Boot мы можем установить следующее свойство в файле application.properties, чтобы отключить fail_on_empty_beans глобально:

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

Это свойство может быть установлено на уровне приложения для управления поведением сериализации Джексона во всем приложении.

5. Заключение

В этой статье показано, как обойти видимость полей по умолчанию в Jackson, настроив пользовательскую видимость либо глобально в ObjectMapper, либо в отдельных классах. Jackson допускает еще большую настройку, предоставляя опции для точного управления тем, как получатели, установщики или поля с определенной видимостью отображаются картографом.

Оригинал статьи: https://www.baeldung.com/jackson-jsonmappingexception