Как исправить ошибку Jackson 'Unrecognized field': Полное руководство
Узнайте, как устранить ошибку Jackson 'Unrecognized field' при парсинге JSON в Java объекты. Полные решения с примерами кода для аннотации @JsonProperty и конфигурации ObjectMapper.
Как решить ошибку разбора JSON в Jackson: “Неопознанное поле ‘wrapper’, не помеченное как игнорируемое” при преобразовании JSON в Java-объект? Я пытаюсь разобрать следующую JSON-структуру с помощью Jackson: {“wrapper”:[{“id”:“13”,“name”:“Fred”}]}. Мой Java-код использует ObjectMapper.readValue() с классом Wrapper, который содержит List
private void tryReading() {
String jsonStr = "{\"wrapper\":[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = null;
try {
wrapper = mapper.readValue(jsonStr, Wrapper.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wrapper = " + wrapper);
}
Мои классы сущностей:
public class Student {
private String name;
private String id;
//геттеры и сеттеры для name & id здесь
}
public class Wrapper {
private List<Student> students;
//геттеры и сеттеры здесь
}
Ошибка, которую я получаю:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException:
Неопознанное поле "wrapper" (Класс Wrapper), не помеченное как игнорируемое
at [Source: java.io.StringReader@1198891; line: 1, column: 13]
(through reference chain: Wrapper["wrapper"])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
.from(UnrecognizedPropertyException.java:53)
Что я упускаю в своей конфигурации Jackson или структуре классов для правильного отображения JSON-поля wrapper в мой Java-объект?
Проблема, с которой вы столкнулись, возникает потому, что ваш класс Wrapper не имеет поля с именем “wrapper”, а JSON содержит свойство с таким именем. Jackson ожидает прямого соответствия имен полей, если вы не предоставите явные аннотации сопоставления или конфигурацию.
Содержание
- Понимание проблемы
- Решение 1: Добавление отсутствующего поля с правильным сопоставлением
- Решение 2: Использование аннотации @JsonProperty
- Решение 3: Настройка ObjectMapper для игнорирования неизвестных свойств
- Решение 4: Альтернативная структура класса Wrapper
- Полный рабочий пример
- Лучшие практики
Понимание проблемы
Ошибка возникает потому, что ваша структура JSON имеет верхнеуровневое свойство с именем “wrapper”, содержащее массив объектов Student, но ваш класс Wrapper имеет поле с именем “students” вместо “wrapper”. По умолчанию Jackson требует точного соответствия имен полей между JSON и Java-объектами.
Как указано в ответе на Stack Overflow, “Jackson жалуется, потому что не может найти поле в вашем классе Wrapper с именем wrapper. Он делает это, потому что ваш JSON-объект имеет свойство с именем wrapper”.
Решение 1: Добавление отсутствующего поля с правильным сопоставлением
Наиболее прямое решение - добавить поле с именем “wrapper” в ваш класс Wrapper, которое содержит List<Student>:
public class Wrapper {
private List<Student> wrapper; // Измените имя поля, чтобы соответствовать JSON
//геттеры и сеттеры здесь
}
Этот подход поддерживает точное соответствие имен полей между JSON и Java-объектами.
Решение 2: Использование аннотации @JsonProperty
Более гибкий подход - использование аннотации @JsonProperty для сопоставления имени JSON-поля с именем Java-поля. Это позволяет сохранить существующее соглашение об именовании полей, при этом поддерживая структуру JSON:
public class Wrapper {
@JsonProperty("wrapper") // Сопоставляет JSON-поле "wrapper" с этим Java-полем
private List<Student> students;
//геттеры и сеттеры здесь
}
Как упоминается в статье на SkillVertex, “Вы можете использовать аннотации, такие как @JsonProperty, для сопоставления имен JSON-полей с полями вашего Java-класса”.
Решение 3: Настройка ObjectMapper для игнорирования неизвестных свойств
Если вы хотите, чтобы Jackson игнорировал свойства, не соответствующие каким-либо Java-полям, вы можете соответствующим образом настроить ваш ObjectMapper:
private void tryReading() {
String jsonStr = "{\"wrapper\":[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
// Настройка игнорирования неизвестных свойств
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Wrapper wrapper = null;
try {
wrapper = mapper.readValue(jsonStr, Wrapper.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wrapper = " + wrapper);
}
Этот подход полезен, когда вы хотите быть более гибкими при работе с входящими JSON-данными и игнорировать дополнительные поля.
Решение 4: Альтернативная структура класса Wrapper
Для сложных структур JSON с обертками массивов может потребоваться скорректировать структуру вашего класса. Как отмечено в статье на Java Code Geeks, “Чтобы правильно разобрать JSON-строку, нам нужно создать класс-обертку, который будет иметь атрибут для хранения массива Person.”
public class Wrapper {
@JsonProperty("wrapper")
private List<Student> students;
// Альтернатива: если вы хотите получить прямой доступ к полю wrapper
@JsonProperty("wrapper")
private List<Student> wrapper;
// Вы можете иметь оба поля при необходимости
public List<Student> getStudents() {
return wrapper; // или return students в зависимости от ваших предпочтений
}
public void setStudents(List<Student> students) {
this.wrapper = students; // или this.students = students
}
}
Полный рабочий пример
Вот полный рабочий пример, использующий подход с аннотациями:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class Student {
private String name;
private String id;
// Геттеры и Сеттеры
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getId() { return id; }
public void setId(String id) { this.id = id; }
@Override
public String toString() {
return "Student{id='" + id + "', name='" + name + "'}";
}
}
public class Wrapper {
@JsonProperty("wrapper")
private List<Student> students;
// Геттеры и Сеттеры
public List<Student> getStudents() { return students; }
public void setStudents(List<Student> students) { this.students = students; }
@Override
public String toString() {
return "Wrapper{students=" + students + "}";
}
}
private void tryReading() {
String jsonStr = "{\"wrapper\":[{\"id\":\"13\",\"name\":\"Fred\"}]}";
ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = null;
try {
wrapper = mapper.readValue(jsonStr, Wrapper.class);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("wrapper = " + wrapper);
if (wrapper != null && wrapper.getStudents() != null) {
wrapper.getStudents().forEach(System.out::println);
}
}
Лучшие практики
- Используйте аннотации @JsonProperty для явного сопоставления полей, когда имена JSON и Java полей различаются
- Рассмотрите поведение fail-fast - решите, хотите ли вы, чтобы Jackson завершался с ошибкой при неизвестных свойствах или игнорировал их
- Проверяйте структуру JSON - убедитесь, что она соответствует ожидаемой структуре Java-объекта
- Обрабатывайте крайние случаи - учтите пустые массивы, нулевые значения и отсутствующие поля
- Используйте правильную обработку ошибок - перехватывайте и обрабатывайте специфичные исключения Jackson соответствующим образом
Как предлагает Baeldung, “Цель состоит в том, чтобы просто игнорировать любые свойства JSON, которые не могут быть сопоставлены с существующим Java-полем”, когда вы хотите более гибкий разбор.
Выберите решение, которое лучше всего соответствует требованиям вашего приложения с точки зрения поддерживаемости и гибкости.
Источники
- Jackson with JSON: Unrecognized field, not marked as ignorable - Stack Overflow
- How to Solve UnrecognizedPropertyException: Unrecognized field, not marked as ignorable - Java Code Geeks
- Jackson With JSON: Unrecognized Field, Not Marked As Ignorable - SkillVertex
- Resolving Jackson JSON Parsing Error: Unrecognized Field Not Marked as Ignorable - CodingTechRoom
- Jackson Unmarshalling JSON with Unknown Properties - Baeldung
Заключение
Исключение “UnrecognizedPropertyException” Jackson возникает при несоответствии между именами полей JSON и Java-объектов. Вы можете решить эту проблему:
- Добавив поле с именем “wrapper” для соответствия структуре JSON
- Используя аннотацию @JsonProperty для сопоставления JSON “wrapper” с Java-полем “students”
- Настроив ObjectMapper на игнорирование неизвестных свойств
- Адаптировав структуру класса для лучшего соответствия формату JSON
Выберите подход, который лучше всего соответствует требованиям вашего приложения с точки зрения поддерживаемости, гибкости и строгости. Подход с использованием аннотации @JsonProperty часто является наиболее поддерживаемым решением для производственных приложений.