Серіалізація з Джексоном (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 в якості першого аргументу. Еквівалентний onelinermyObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Ден Робінсон

@DanRobinson Я використовував те саме. Але насправді я генерую файл yaml. так що для JSONString як: {"term":{"call_failed":"true"}}він генерує структуру yaml як: filter: map: term: map: call_failed: "true"Чому він генерує mapключове слово? Як я можу її видалити?
Маніш Кумар

7
Я, мабуть, провів 8 годин з цією помилкою, не розуміючи, що в моєму методі геттера на ньому немає "загальнодоступних". Так дурно
Майк Келлогг

1
Я отримую цю помилку під час перетворення ClientResponse в рядок за допомогою об'єктного картографування
VdeX

1
Ви також можете додати анотацію @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)вище свого класу
veben

74

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


5
Зверніть увагу , ця відповідь невірний - полі не потрібно бути відкритими або мати геттер і сетер. В іншій відповіді на це питання я запропонував альтернативну конфігурацію, яка не вимагає (де) серіалізації змін в початковій структурі даних.
Програміст Брюс

9
Відповідь корисна, навіть якщо не на 100% точно правильна. Я забув поставити "громадськість" на свої роки, і це вказувало на це. Дякую!
ChrisPhoenix

53

У мене така ж проблема у моєму вихідному коді. Я щойно додав

геттер

і

сетер

проблема вирішена.


1
Спробував багато різних речей, і рішення настільки ж просто, як це .... і це чітко сказано: "не було виявлено властивостей, які можна створити".
акс

2
@PhilipRego Це означає, що він додав геттер і сетер для поля.
Пол,

Я використовую бібліотеку lombok, тому я просто додаю анотацію Getter та Setter. І все було добре. Дякую.
Рахмат Хідаят

так, геттери та сетери використовуються для серіалізації Джексона
./deserialization

25

Проблема в моєму випадку полягала в тому, що Джексон намагався серіалізувати порожній об'єкт без атрибутів і методів.

Як запропоновано у винятку, я додав наступний рядок, щоб уникнути виходу з ладу на пусту квасолю

Для Джексона 1.9

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

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

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Ви можете знайти простий приклад на jackson disabled 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
AlikElzin-kilaka

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
Ласкаво просимо до SO! Дякуємо за ваш внесок. Будь ласка, додайте пояснення до своєї відповіді, щоб було зрозуміло, що робить код, чому він працює і як відповідає на питання ОП.
Макс Волмер

Це мені допомогло! Але, на мою думку, слід вводити ObjectMapper контексту та конфігурувати його згодом, а не створювати новий.
RoBeaToZ

3

Для додатків Oracle Java додайте це після ObjectMapperстворення екземпляра:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

2

У мене була подібна проблема з ледачим завантаженням через сплячий проксі-об'єкт. Подолав це, анотувавши клас, який ледаче завантажував приватні властивості, використовуючи:

@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

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

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.