Сериализация с Джексоном (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;

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

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

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);. Этого следует избегать, если вам не нужны эти функции во всем мире.

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


2

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

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

1

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

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})

1

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

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}


0

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


0

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.