Другое

Как исправить ошибку 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, но я постоянно получаю UnrecognizedPropertyException. Вот моя текущая реализация:

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

Мои классы сущностей:

java
public class Student { 
    private String name;
    private String id;
    //геттеры и сеттеры для name & id здесь
}
java
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 ожидает прямого соответствия имен полей, если вы не предоставите явные аннотации сопоставления или конфигурацию.

Содержание

Понимание проблемы

Ошибка возникает потому, что ваша структура JSON имеет верхнеуровневое свойство с именем “wrapper”, содержащее массив объектов Student, но ваш класс Wrapper имеет поле с именем “students” вместо “wrapper”. По умолчанию Jackson требует точного соответствия имен полей между JSON и Java-объектами.

Как указано в ответе на Stack Overflow, “Jackson жалуется, потому что не может найти поле в вашем классе Wrapper с именем wrapper. Он делает это, потому что ваш JSON-объект имеет свойство с именем wrapper”.

Решение 1: Добавление отсутствующего поля с правильным сопоставлением

Наиболее прямое решение - добавить поле с именем “wrapper” в ваш класс Wrapper, которое содержит List<Student>:

java
public class Wrapper {
    private List<Student> wrapper; // Измените имя поля, чтобы соответствовать JSON
    
    //геттеры и сеттеры здесь
}

Этот подход поддерживает точное соответствие имен полей между JSON и Java-объектами.

Решение 2: Использование аннотации @JsonProperty

Более гибкий подход - использование аннотации @JsonProperty для сопоставления имени JSON-поля с именем Java-поля. Это позволяет сохранить существующее соглашение об именовании полей, при этом поддерживая структуру JSON:

java
public class Wrapper {
    @JsonProperty("wrapper")  // Сопоставляет JSON-поле "wrapper" с этим Java-полем
    private List<Student> students;
    
    //геттеры и сеттеры здесь
}

Как упоминается в статье на SkillVertex, “Вы можете использовать аннотации, такие как @JsonProperty, для сопоставления имен JSON-полей с полями вашего Java-класса”.

Решение 3: Настройка ObjectMapper для игнорирования неизвестных свойств

Если вы хотите, чтобы Jackson игнорировал свойства, не соответствующие каким-либо Java-полям, вы можете соответствующим образом настроить ваш ObjectMapper:

java
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.”

java
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
    }
}

Полный рабочий пример

Вот полный рабочий пример, использующий подход с аннотациями:

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

Лучшие практики

  1. Используйте аннотации @JsonProperty для явного сопоставления полей, когда имена JSON и Java полей различаются
  2. Рассмотрите поведение fail-fast - решите, хотите ли вы, чтобы Jackson завершался с ошибкой при неизвестных свойствах или игнорировал их
  3. Проверяйте структуру JSON - убедитесь, что она соответствует ожидаемой структуре Java-объекта
  4. Обрабатывайте крайние случаи - учтите пустые массивы, нулевые значения и отсутствующие поля
  5. Используйте правильную обработку ошибок - перехватывайте и обрабатывайте специфичные исключения Jackson соответствующим образом

Как предлагает Baeldung, “Цель состоит в том, чтобы просто игнорировать любые свойства JSON, которые не могут быть сопоставлены с существующим Java-полем”, когда вы хотите более гибкий разбор.

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

Источники

  1. Jackson with JSON: Unrecognized field, not marked as ignorable - Stack Overflow
  2. How to Solve UnrecognizedPropertyException: Unrecognized field, not marked as ignorable - Java Code Geeks
  3. Jackson With JSON: Unrecognized Field, Not Marked As Ignorable - SkillVertex
  4. Resolving Jackson JSON Parsing Error: Unrecognized Field Not Marked as Ignorable - CodingTechRoom
  5. Jackson Unmarshalling JSON with Unknown Properties - Baeldung

Заключение

Исключение “UnrecognizedPropertyException” Jackson возникает при несоответствии между именами полей JSON и Java-объектов. Вы можете решить эту проблему:

  • Добавив поле с именем “wrapper” для соответствия структуре JSON
  • Используя аннотацию @JsonProperty для сопоставления JSON “wrapper” с Java-полем “students”
  • Настроив ObjectMapper на игнорирование неизвестных свойств
  • Адаптировав структуру класса для лучшего соответствия формату JSON

Выберите подход, который лучше всего соответствует требованиям вашего приложения с точки зрения поддерживаемости, гибкости и строгости. Подход с использованием аннотации @JsonProperty часто является наиболее поддерживаемым решением для производственных приложений.

Авторы
Проверено модерацией
Модерация