Одна из распространенных проблем при синтаксическом анализе 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, являются их собственными. |
