Рубрики
Без рубрики

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

Как исправить исключение Jackson 2 JsonMappingException (сериализатор для класса не найден).

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