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

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

1. обзор

В этом кратком руководстве мы проанализируем маршалинг сущностей без геттеров иthe solution for the Jackson JsonMappingException exception.

Если вы хотите копнуть глубже и изучитьother cool things you can do with the Jackson 2 - переходите кthe main Jackson tutorial.

Дальнейшее чтение:

Введение в Джексон ObjectMapper

В статье обсуждается центральный класс ObjectMapper Джексона, базовая сериализация и десериализация, а также настройка этих двух процессов.

Read more

Использование опционально с Джексоном

Краткий обзор того, как мы можем использовать Дополнительный с Джексоном.

Read more

Пружина JSON-P с Джексоном

В статье рассказывается, как использовать новую поддержку JSON-P в Spring 4.1.

Read more

2. Эта проблема

По умолчанию Jackson 2 будет работать только с общедоступными полями или с общедоступными методами получения -serializing an entity that has all fields private or package private will fail:

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

full exception:

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. Решение

Очевидное решение заключается в добавлении геттеров для полей - если объект находится под нашим контролем. Если это не так иmodifying the source of the entity is not possible - тогда Джексон предлагает нам несколько альтернатив.

3.1. Глобальное автоматическое определение полей с любой видимостью

Первое решение этой проблемы - глобальная настройкаObjectMapper для обнаружения всех полей, независимо от их видимости:

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Это будетallow the private and package private fields to be detected без геттеров, и сериализация будет работать правильно:

@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, - вместо глобальной конфигурации -control the field visibility at the class level через аннотацию@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. Заключение

В этой статье показано, как выполнитьget around the default field visibility in Jackson, настроив настраиваемую видимость глобально дляObjectMapper или для отдельных классов. Джексон позволяет еще больше настраивать, предоставляя опции для точного управления тем, как преобразователи видят получатели, установщики или поля с определенной видимостью.

Реализация всех этих примеров и фрагментов кодаcan be found in my github project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.