Статьи

Как игнорировать неизвестные свойства при разборе JSON в Java — пример аннотации Джексона @JsonIgnoreProperties

Одна из распространенных проблем при синтаксическом анализе JSON в Java с использованием Jackson API заключается в том, что происходит сбой, когда ваш JSON содержит неизвестные свойства, т. Е. Ваш класс Java не имеет всех полей, соответствующих всем свойствам JSON. Например, если вы используете JSON из веб-службы REST, а завтра они добавят новое поле в JSON, тогда ваш код прервется, потому что Джексон выдаст исключение UnrecognizedPropertyException и прекратит синтаксический анализ JSON. Это хлопотно и может вызвать проблемы на производстве, если вы не знаете. Я столкнулся с этой проблемой, когда разработчик отправил код для использования данных из REST API без надлежащей обработки неизвестных полей.

Код работал отлично в течение нескольких месяцев, но он сломался, как только в исходную систему было добавлено новое поле, добавленное в REST API. Разработчик предпочитает игнорировать обновление, потому что мы не были заинтересованы в этой области, но он не смог предвидеть, что это повлияет на анализ JSON .

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

Jackson API предоставляет два способа игнорирования неизвестных полей : первый на уровне класса с @JsonIgnoreProperties аннотации @JsonIgnoreProperties и второй на уровне @JsonIgnoreProperties с configure() метода configure() .

В этой статье вы увидите оба подхода и узнаете, как их использовать и когда использовать <@code> JsonIgnoreProperties, а также когда игнорировать неизвестные поля в JSON глобально на уровне ObjectMapper .

Игнорирование неизвестных свойств с использованием @JsonIgnoreProperties

Если вы создаете класс Model для представления JSON в Java, вы можете аннотировать класс с помощью @JsonIgnoreProperties (ignoreUnknown = true), чтобы игнорировать любое неизвестное поле. Это означает, что если завтра в JSON будет добавлено новое поле, представляющее вашу модель, то Джексон не сгенерирует UnrecognizedPropertyException при анализе JSON в Java.

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

Давайте посмотрим пример использования @JsonIgnoreProperties в Java:

Предположим, у меня есть следующий JSON, представляющий мою любимую книгу, Effective Java 3rd Edition , обязательную для чтения книгу для каждого разработчика Java в 2018 году и класс модели Java в моем проекте:

Если завтра я добавлю новое поле с именем «edition» в JSON, то синтаксический анализ этого JSON завершится с ошибкой UnrecognizedPropertyException . Что-то типа :

Исключение в потоке «main» com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: нераспознанное поле «edition» (класс EBook), не помеченное как игнорируемое (3 известных свойства:, «title», «price», «author»] )»

Это означает, что Джексон не может найти какое-либо поле в вашем классе EBook для свойства «edition» в JSON и, следовательно, UnrecognizedPropertyException ошибку UnrecognizedPropertyException .

Вы можете решить эту проблему и предотвратить эту ошибку с помощью аннотации @JsonIgnoreProperties как показано ниже:

1
2
3
4
5
6
7
8
@JsonIgnoreProperties(ignoreUnknown = true)
class EBook{
  private String title;
  private String author;
  private int price;
  ..
 
}

Мы только что аннотировали целый класс модели как @JsonIgnoreProperties (ignoreUnknown = true), что означает любое неизвестное свойство в JSON String, т.е. любое свойство, для которого у нас нет соответствующего поля в классе EBook, будет игнорироваться. Если вы скомпилируете и снова запустите свою программу, она будет работать нормально.

В Jackson 2.x @JsonIgnoreProperties находятся в пакете com.fasterxml.jackson.annotation, поэтому вам нужно импортировать его как:

импорт com.fasterxml.jackson.annotation.JsonIgnoreProperties.

Если вы используете более старую версию Jackson API, например, Jackson 1.x, эта аннотация относится к другому пакету, будьте осторожны, особенно если у вас есть и Jackson 1.x, и Jackson 2.x в вашем classpath.

Игнорирование неизвестного свойства в JSON глобально с использованием Jackson

Другой способ справиться с неизвестными свойствами в JSON, который вы анализируете, — это настроить ObjectMapper чтобы он не ObjectMapper сбоем, когда он встречает неизвестное свойство. Это также решит проблему UnrecognizedPropertyException . Вы можете включить этот параметр, вызвав метод configure (), как показано ниже:

1
2
3
4
5
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
 
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

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

Кстати, если вы не знакомы с библиотеками синтаксического анализа JSON в Java, то JSON с API-интерфейсами Java, jQuery и REST Web Services в Udemy — это хорошее место для начала.

Java-программа для игнорирования неизвестных свойств при разборе JSON с использованием Jackson

Давайте посмотрим, что мы узнали в действии. Кстати, если вы запутались с моим String JSON и большим количеством строк «/ r / n», не волнуйтесь. Я не делал это вручную. Я использовал это
Трюк Eclipse для копирования моего JSON, и он автоматически включает необходимые escape-символы. Это необходимо, потому что строка JSON заключена в двойные кавычки («»), которые необходимо экранировать в Java.

Кстати, если вы новичок в Eclipse IDE, то я советую вам изучить Учебный курс по Eclipse Java IDE для начинающих, чтобы изучить его. Разработчику Java важно хорошо знать свои инструменты, особенно IDE, чтобы они могли эффективно разрабатывать, тестировать, отлаживать и запускать свои приложения Java.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 
/*
 * Java Program to iterate over JSONObject of json-simple
 */
public class JacksonTest {
 
  private static String json = "{\r\n" + "\"title\" : \"Effective Java\",\r\n"
      + "\"author\" : \"Joshua Bloch\",\r\n" + "\"price\" : 37,\r\n"
      + "\"edition\" : 37\r\n" + "}";
 
  public static void main(String args[]) throws IOException {
 
    // let's parse JSON with a date field
    ObjectMapper mapper = new ObjectMapper();
    // mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
    // false);
 
    EBook effectiveJava = mapper.readValue(json, EBook.class);
    System.out.println("Input json string");
    System.out.println(json);
    System.out.println("Generated java class: ");
    System.out.println(effectiveJava);
 
  }
 
}
 
class EBook {
  private String title;
  private String author;
  private int price;
 
  public EBook() {
    // no argument constructor required by Jackson
  }
 
  public EBook(String title, String author, int price) {
    this.title = title;
    this.author = author;
    this.price = price;
  }
 
  public String getTitle() {
    return title;
  }
 
  public String getAuthor() {
    return author;
  }
 
  public int getPrice() {
    return price;
  }
 
  public void setTitle(String title) {
    this.title = title;
  }
 
  public void setAuthor(String author) {
    this.author = author;
  }
 
  public void setPrice(int price) {
    this.price = price;
  }
 
  @Override
  public String toString() {
    return "EBook [title=" + title + ", author=" + author + ", price=" + price
        + "]";
  }
 
}
 
Output:
Input json string
{
"title" : "Effective Java",
"author" : "Joshua Bloch",
"price" : 37,
"version" : 37
}
Generated java class:
EBook [title=Effective Java, author=Joshua Bloch, price=37]

У меня есть класс модели под названием EBook, который аннотируется @JsonIgnoreProperties (ignoreUnknown = true), чтобы игнорировать неизвестные свойства.

Если вы посмотрите внимательно, наша строка JSON содержит свойство «edition», которое не определено в классе Java, но программа работает, потому что мы пометили EBook @JsonIgnoreProperties (ignoreUnknown = true).

Если вы хотите протестировать эту программу, просто удалите эту аннотацию и запустите программу, она выдаст следующую ошибку.

01
02
03
04
05
06
07
08
09
10
11
12
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field
 "edition" (class EBook), not marked as ignorable (3 known properties: , "title", "price", "author"])
at [Source: java.io.StringReader@19dfb72a; line: 5, column: 14] (through reference chain: EBook["edition"])
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 JacksonTest.main(JacksonTest.java:30)

Это произошло из-за поля «edition», которое присутствует только в JSON, а не в классе Java. Если вы поместите аннотацию обратно, код снова заработает.

Аналогичным образом вы можете проверить, как игнорировать неизвестное поле на уровне отображения объектов , вместо того, чтобы @JsonIgnoreProperties аннотацию @JsonIgnoreProperties обратно, вы просто раскомментируете
mapper.configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) в строке кода и запустите программу. На этот раз это также будет работать, потому что Джексон игнорирует все неизвестные свойства.

Это все о том, как игнорировать неизвестные свойства при разборе JSON в Java с помощью Jackson API . Вы можете сделать это либо с помощью аннотации @JsonIgnoreProperties либо сконфигурировав ObjectMapper чтобы он не @JsonIgnoreProperties сбоев при обнаружении неизвестных свойств во время десериализации путем отключения FAIL_ON_UNKNOWN_PROPERTIES.

Хотя предпочтительный подход заключается в том, чтобы игнорировать неизвестные свойства на уровне класса с помощью @JsonIgnoreProperties (ignoreUnknown = true) и делать это только на уровне ObjectMapper если вы не можете аннотировать свой класс этой аннотацией, т.е. вы не являетесь владельцем класса. Рекомендуется также аннотировать класс вашей модели с помощью @JsonIgnoreProperties чтобы избежать проблемы, @JsonIgnoreProperties в первом абзаце.

Другие ресурсы Java и JSON, которые могут вам понравиться

JSON в действии: создание приложений на основе JSON
Как разобрать JSON с помощью Gson?
5 библиотек анализа JSON, которые должны знать Java-разработчики
Как разобрать массив JSON в Java?
Как конвертировать JSON в HashMap в Java?
10 вещей, которые Java-разработчик должен выучить в 2018 году
JSON с Java API, jQuery и REST Web Services

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

См. Оригинальную статью здесь: Как игнорировать неизвестные свойства при анализе JSON в Java — пример аннотации Jackson @JsonIgnoreProperties

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