Статьи

Ошибка синтаксического анализа JSON Джексона — UnrecognizedPropertyException: нераспознанное поле, не помеченное как игнорируемое [решено]

При синтаксическом анализе строки JSON, полученной от одного из наших веб-сервисов RESTful, я получал эту ошибку «Исключение в потоке« main »com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: нераспознанное поле« person »(класс Hello $ Person), а не помечен как игнорируемый » .

После некоторых исследований я обнаружил, что это одна из распространенных ошибок при анализе документа JSON с использованием библиотеки с открытым исходным кодом Jackson в приложении Java. В сообщениях об ошибках говорится, что в нашем случае невозможно найти подходящее имя свойства с именем person, давайте сначала рассмотрим JSON, который мы пытаемся проанализировать, класс, который мы используем для представления документа JSON, и ошибку само сообщение

Сообщение об ошибке:

1
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: <b>Unrecognized field "person"</b> (class Hello$Person), not marked as ignorable (4 known properties: , "id", "city", "name", "phone"])

В сообщениях об ошибках говорится, что он может определить атрибуты id, city, name и phone в классе Person, но не может найти поле «person».

Наш класс POJO выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
class Person{
 
private int id;
 
private String name;
 
private String city;
 
private long phone;
 
.....
 
}

и строка JSON:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
{
 
"person": [
 
{
 
"id": "11",
 
"name": "John",
 
"city": "NewYork",
 
"phone": 7647388372
 
}
 
]
 
}

Если вы посмотрите внимательно, поле «person» указывает на массив JSON, а не на объект, что означает, что его нельзя напрямую сопоставить с классом person.

Как решить эту проблему

Вот шаги, чтобы решить эту проблему и избавиться от этой ошибки:

1) Сконфигурируйте ObjectMapper Джексона, чтобы он не завершался ошибкой, когда привлекает неизвестные свойства

Вы можете сделать это, отключив свойство D eserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES как показано ниже:

1
2
3
4
5
6
7
8
9
// Jackson code to convert JSON String to Java object
 
ObjectMapper objectMapper = new ObjectMapper();
 
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
Person p = objectMapper.readValue(JSON, Person.class);
 
System.out.println(p);

Теперь ошибка исчезнет, ​​но вывод не соответствует ожидаемому, он выведет следующее:

1
Person [id=0, name=null, city=null, phone=0]

Вы можете видеть, что класс Person не создан должным образом, соответствующие атрибуты имеют значение null, даже если строка JSON содержит его значение.

Причина в том, что JSON String содержит массив JSON , поле person указывает на массив, и в классе Person нет соответствующего ему поля.

Чтобы правильно проанализировать строку JSON, нам нужно создать класс-оболочку Community которого будет атрибут для хранения массива Person, как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
12
static class Community {
  private List<Person> person;
 
  public List<Person> getPerson() {
    return person;
  }
 
  public void setPerson(List<Person> person) {
    this.person = person;
  }
 
}

Теперь мы преобразуем строку JSON в этот класс Community и напечатаем каждого человека из списка, как показано ниже:

01
02
03
04
05
06
07
08
09
10
11
ObjectMapper objectMapper = new ObjectMapper();
 
//objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
Community c = objectMapper.readValue(JSON, Community.class);
 
for (Person p : c.getPerson()) {
 
System.out.println(p);
 
}

Это распечатает данные человека должным образом, как показано ниже:

1
Person [id=11, name=John, city=NewYork, phone=7647388372]

Теперь, возвращаясь к более общей ситуации, когда новое поле добавляется в JSON, но недоступно в вашем классе Person , давайте посмотрим, что произойдет.

Предположим, что наша строка JSON для разбора выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
{
 
"person": [
 
{
 
"id": "11",
 
"name": "John",
 
"city": "NewYork",
 
"phone": 7647388372,
 
"facebook": "JohnTheGreat"
 
}
 
]
 
}

Когда вы запустите ту же программу с этой строкой JSON , вы получите следующую ошибку:

Опять же, Джексон не может распознать новое свойство «Facebook». Теперь мы можем игнорировать это свойство, отключив функцию, которая сообщает Джексону об отказе в неизвестном свойстве, как показано ниже:

1
2
3
4
5
ObjectMapper objectMapper = new ObjectMapper();
 
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
 
Community c = objectMapper.readValue(JSON, Community.class);

И это правильно напечатает класс person, как показано ниже:

1
Person [id=11, name=John, city=NewYork, phone=7647388372]

Кроме того, вы также можете использовать аннотацию @JsonIgnoreProperties чтобы игнорировать необъявленные свойства.

@JsonIgnoreProperties — это аннотация уровня класса в Джексоне, и она будет игнорировать все свойства, которые вы не определили в своем POJO. Очень полезно, когда вы просто ищете пару свойств в JSON и не хотите писать полное отображение.

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

1
@JsonIgnoreProperties(ignoreUnknown = true)

Итак, наш класс Person теперь выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
@JsonIgnoreProperties(ignoreUnknown = true)
 
static class Person{
 
private int id;
 
private String name;
 
private String city;
 
private long phone;
 
......
 
}

Пример программы

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
import java.io.IOException;
import java.util.List;
 
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
 
/*
 * {
 "person": [
 {
 "id": "11",
 "name": "John",
 "city": "NewYork",
 "phone": 7647388372
 }
 ]
 }
 */
 
public class Hello {
 
  private static String JSON = "{\r\n" + " \"person\": [\r\n" + " {\r\n"
      + " \"id\": \"11\",\r\n" + " \"name\": \"John\",\r\n"
      + " \"city\": \"NewYork\",\r\n" + " \"phone\": 7647388372,\r\n"
      + " \"facebook\": \"JohnTheGreat\"\r\n" + " }\r\n" + " ]\r\n" + " } ";
 
  public static void main(String args[]) throws JsonParseException,
      JsonMappingException, IOException {
 
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    Community c = objectMapper.readValue(JSON, Community.class);
 
    for (Person p : c.getPerson()) {
      System.out.println(p);
    }
 
  }
 
  static class Community {
    private List<Person> person;
 
    public List<Person> getPerson() {
      return person;
    }
 
    public void setPerson(List<Person> person) {
      this.person = person;
    }
 
  }
 
  static class Person {
    private int id;
    private String name;
    private String city;
    private long phone;
 
    public int getId() {
      return id;
    }
 
    public void setId(int id) {
      this.id = id;
    }
 
    public String getName() {
      return name;
    }
 
    public void setName(String name) {
      this.name = name;
    }
 
    public String getCity() {
      return city;
    }
 
    public void setCity(String city) {
      this.city = city;
    }
 
    public long getPhone() {
      return phone;
    }
 
    public void setPhone(long phone) {
      this.phone = phone;
    }
 
    @Override
    public String toString() {
      return "Person [id=" + id + ", name=" + name + ", city=" + city
          + ", phone=" + phone + "]";
    }
 
  }
}

Когда я запускаю первую версию этой программы, меня встречает следующая ошибка:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class Hello$Person]: can not instantiate from JSON object (need to add/enable type information?)
 
at [Source: java.io.StringReader@5e329ba8; line: 2, column: 3]
 
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
 
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
 
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
 
at Hello.main(Hello.java:40)

Эта ошибка произошла из-за того, что мой вложенный класс Person не был статичным, что означает, что его нельзя создать из-за наличия экземпляра внешнего класса. Проблема решена после того, как класс Person статическим .

Если вы не знакомы с этой деталью раньше, я предлагаю вам проверить
Основы Java: Базовая платформа , бесплатный курс от Pluralsight, чтобы узнать больше о таких деталях языка программирования Java. Вы можете подписаться на бесплатную пробную версию, которая дает вам 10-дневный доступ, достаточный для изучения всей Java бесплатно.

Теперь посмотрим на реальную ошибку:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: <b>Unrecognized field "person" (class Hello$Person), not marked as ignorable</b> (4 known properties: , "id", "city", "name", "phone"])
 
at [Source: java.io.StringReader@4fbc9499; line: 2, column: 14] (through reference chain: Person["person"])
 
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
 
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555)
 
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1160)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:315)
 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
 
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
 
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
 
at Hello.main(Hello.java:40)

Когда вы запустите финальную версию программы, вы увидите следующий вывод:

1
Person [id=11, name=John, city=NewYork, phone=7647388372]

Это означает, что мы можем успешно проанализировать JSON, содержащий неизвестные атрибуты в Джексоне.

Как скомпилировать и запустить эту программу?

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

В Eclipse вам даже не нужно создавать файл класса, потому что он автоматически создаст класс и пакет, если вы скопируете и вставите код в проект Java.

Если Eclipse является вашей основной IDE и вы хотите узнать больше о таких советах по производительности, я предлагаю вам проверить
Экскурсия «Затмение» — часть 1 и 2 Тод Джентилл .

Это бесплатный онлайн-курс для изучения как основных, так и расширенных возможностей Eclipse IDE, о которых должен знать каждый разработчик Java. Вы можете получить доступ к этому курсу, подписавшись на бесплатную пробную версию, которая дает вам 10-дневный доступ ко всей библиотеке Pluralsight, одной из самых ценных коллекций для изучения программирования и других технологий. Кстати, 10 дней более чем достаточно для изучения Java и Eclipse вместе.

В любом случае, после копирования вставьте код, все, что вам нужно сделать, это включить зависимость Maven в ваш файл pom.xml или вручную загрузить требуемый JAR-файл для библиотеки с открытым исходным кодом Jackson .

Для пользователей Maven

Вы можете добавить следующую зависимость Maven к pom.xml вашего проекта, а затем выполнить команду mvn build или mvn install для компиляции:

1
2
3
4
5
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.2.3</version>
</dependency>

Эта зависимость требует jackson-annotations jackson-core и jackson-annotations но Maven автоматически загрузит их для вас.

Загрузка JAR вручную

Если вы не используете Maven или какой-либо другой инструмент сборки eggradle, вы можете просто зайти в центральную библиотеку Maven и загрузить следующие три JAR-файла и включить их в ваш путь к классам:

1
2
3
jackson-databind-2.2.3.jar
jackson-core-2.2.3.jar
jackson-annotations-2.2.3.jar

После того, как вы успешно скомпилировали класс, вы можете запустить их, как и любую другую программу на Java в Eclipse, как показано здесь, или вы можете запустить файл JAR с помощью командной строки, как показано
здесь

Короче говоря, ошибка « com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: нераспознанное поле XXX, не помеченное как игнорируемое» возникает при попытке проанализировать JSON для объекта Java, который не содержит все поля, определенные в JSON. Эту ошибку можно устранить, отключив функцию Джексона, которая сообщает об ошибке при обнаружении неизвестных свойств, или используя аннотацию @JsonIgnoreProperties на уровне класса.

Дальнейшее обучение

Спасибо за чтение этой статьи до сих пор. Если вам нравится мое объяснение, поделитесь с друзьями и коллегами. Если у вас есть какие-либо вопросы или пожелания, напишите нам.

См. Оригинальную статью здесь: Ошибка синтаксического анализа JSON Джексона — UnrecognizedPropertyException: нераспознанное поле, не помеченное как игнорируемое [решено]

Мнения, высказанные участниками Java Code Geeks, являются их собственными.