Сериализация с Джексоном (JSON) - получение «Не найден сериализатор»?

262

Я получаю исключение при попытке сериализации очень простого объекта с использованием Джексона. Ошибка:

org.codehaus.jackson.map.JsonMappingException: не найден сериализатор для класса MyPackage.TestA и не обнаружены свойства для создания BeanSerializer (во избежание исключения отключите SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

Ниже приведен простой класс и код для сериализации.

Может кто-нибудь сказать, почему я получаю эту ошибку?

public class TestA {
    String SomeString = "asd";
}

TestA testA = new TestA();
ObjectMapper om = new ObjectMapper();
try {
    String testAString = om.writeValueAsString(testA); // error here!

    TestA newTestA = om.readValue(testAString, TestA.class);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
Тед
источник
Я написал пост о том, как написать пользовательский сериализатор с Джексоном, который может быть полезным для некоторых.
Сэм Берри

Ответы:

329

Как уже было сказано, конфигурация по умолчанию для ObjectMapperэкземпляра заключается в доступе только к свойствам, которые являются открытыми полями или имеют общедоступные методы получения / установки. Альтернативой изменению определения класса, чтобы сделать поле общедоступным или предоставить общедоступный метод получения / установки, является указание (для базового VisibilityChecker) другого правила видимости свойства. Джексон 1.9 обеспечивает ObjectMapper.setVisibility()удобный метод для этого. Для примера в оригинальном вопросе, я бы, вероятно, настроил это как

myObjectMapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

Для Джексона> 2.0:

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

Для получения дополнительной информации и подробностей о связанных параметрах конфигурации, я рекомендую просмотреть JavaDocs наObjectMapper.setVisibility() .

Программист Брюс
источник
59
Это сработало для меня. Начиная с Jackson 2.0, ObjectMapper # setVisibility принимает PropertyAccessor в качестве первого аргумента. Эквивалентный лайнер myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Дэн Робинсон
@DanRobinson Я использовал то же самое. Но на самом деле я генерирую файл yaml. поэтому для JSONString as: {"term":{"call_failed":"true"}}он генерирует структуру yaml как: filter: map: term: map: call_failed: "true"Почему он генерирует mapключевое слово? Как я могу удалить это?
Маниш Кумар
7
Я, вероятно, провел 8 часов с этой ошибкой, не понимая, что в моем методе получения не было "public" ... так глупо
Майк Келлогг
1
Я получаю эту ошибку при преобразовании ClientResponse в строку, используя объект сопоставления
VdeX
1
Вы также можете добавить аннотацию @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)над вашим классом
веб-
74

Чтобы Джексон мог сериализовать этот класс, SomeStringполе должно быть public(прямо сейчас это изоляция на уровне пакета) или вам нужно определить методы получения и установки для него.

Крис
источник
5
Обратите внимание, что этот ответ неправильный - поле не обязательно должно быть общедоступным или иметь методы получения и установки. В другом ответе на этот вопрос я предоставил альтернативную конфигурацию, которая не требует внесения изменений в исходную структуру данных (де) сериализации.
Программист Брюс
9
Ответ полезен, даже если не на 100% точно правильный. Я забыл поставить «public» на мои переменные, и это указало на это. Спасибо!
ChrisPhoenix
54

У меня та же проблема в моем исходном коде. Я только добавил

добытчик

и

сеттер

проблема решена.

Гюнай Гюльтекин
источник
1
Перепробовал много разных вещей, и решение так же просто, как это .... и оно говорит об этом совершенно ясно: "не обнаружено свойств, созданных для создания".
AKS
2
@PhilipRego Он имеет в виду, что он добавил геттер и сеттер для поля.
Пол
Я использую библиотеку lombok, поэтому я просто добавляю аннотации Getter и Setter. И все было хорошо. Спасибо.
Рахмат Хидаят
да, геттеры и сеттеры используются для сериализации Джексона.
десериализация
25

В моем случае проблема заключалась в том, что Джексон пытался сериализовать пустой объект без атрибутов и методов.

Как предложено в исключении, я добавил следующую строку, чтобы избежать сбоя на пустых бинах:

Для Джексона 1,9

myObjectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

Для Джексона 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Вы можете найти простой пример отключения Джексона fail_on_empty_beans

Мартин С
источник
9

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

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
Паван Кумар
источник
7

Если вы можете редактировать класс, содержащий этот объект, я обычно просто добавляю аннотацию

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;
ZiglioUK
источник
2
Эта ошибка также возникает, когда в вашем классе есть метод с именем, начинающимся с get ... Например, NonSerializableClass getMyNonSerializableObject (). Джексон пытается его сериализовать и терпит неудачу. Чтобы решить эту проблему, просто добавьте @JsonIgnore или переименуйте метод.
Алексей Подласов
1
Использовал старую версию:org.codehaus.jackson.annotate.JsonIgnore
АликЭльзин-килака
6

Эта ошибка также выдается, если вы забыли добавить метод .build () в свой статус возврата.

return Response.status(Status.OK);         // fails
return Response.status(Status.OK).build(); // works

Я получил следующую ошибку без метода build ():

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl
patrics
источник
4

SpringBoot2.0 , Я разрешаю это следующим кодом:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}
Янус
источник
1
вы должны сохранить вашу модель с методами получения и установки.
Янус
1
Добро пожаловать на ТАК! Спасибо за помощь. Пожалуйста, добавьте пояснение к своему ответу, чтобы было ясно, что делает код, почему он работает и как он отвечает на вопрос ОП.
Макс Воллмер
Это помогло мне! Но, по моему мнению, вы должны внедрить ObjectMapper контекста и настроить его позже, а не создавать новый.
RoBeaToZ
3

Для приложений Java Java добавьте это после ObjectMapperсоздания экземпляра:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
LEMUEL ADANE
источник
2

У меня была похожая проблема с отложенной загрузкой через прокси-объект hibernate. Обошел его, аннотируя класс с лениво загруженными частными свойствами:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Н. Беруаин
источник
Это решило мою проблему. Можете ли вы сказать мне, что именно это делает?
scarface
2

Проблема может быть в том, что вы объявили переменную как private. Если вы измените его на public, это работает.

Лучший вариант - использовать методы получения и установки для него.

Это решит проблему!

Санчит Сингхания
источник
2

Я нашел по крайней мере три способа сделать это:

  1. Добавьте public gettersсвою сущность, которую вы пытаетесь сериализовать;
  2. Добавьте аннотацию в верхней части объекта, если вы не хотите public getters. Это будет изменить значение по умолчанию для Джексона от Visbility=DEFAULTдо , @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)где любые модификаторы доступа принимаются;
  3. Измените ObjectMapperглобально, установив objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);. Этого следует избегать, если вам не нужны эти функции во всем мире.

Выберите в зависимости от ваших потребностей.

georger
источник
2

Вот три варианта:

  1. Данные / класс, к которому был получен доступ, должны быть public
  2. Если нет public, добавьте геттеры и сеттеры
  3. Или добавить @JsonIgnore("context")
Сантош Кумар
источник
1

Пожалуйста, используйте это на уровне класса для бобов:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
raveendra_bikkina
источник
1

добавление сеттера и геттера также решит проблему, поскольку она исправлена ​​для меня. Например:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}
Сатья Пракаш
источник
1

Просто у меня были только геттеры, после добавления сеттеров тоже проблемы решались.

Ванита Дотре
источник
0

Хотя я добавил геттеры и сеттеры, я получил ту же ошибку. Позже я обнаружил ошибку, то есть по совету Сонара я включил геттеры и сеттеры как защищенные, что и вызвало проблему. Как только я установил, что это работает как ожидалось.

желтый
источник
0

весной багажник 2.2.5

после добавления геттера и сеттера

я добавил @JsonIgnore поверх поля.

саба
источник