1. Обзор
В этой статье мы рассмотрим сравнение двух объектов JSON с помощью Jackson — библиотеки обработки JSON для Java.
2. Зависимость от Maven
Во-первых, давайте добавим зависимость jackson-databind
Maven: ``
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
3. Использование Джексона для сравнения двух объектов JSON
Мы будем использовать класс ObjectMapper
для чтения объекта как JsonNode.
Давайте создадим ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
3.1. Сравните два простых объекта JSON
Начнем с использования метода JsonNode.equals
. Метод equals()
выполняет полное (глубокое) сравнение.
Предположим, у нас есть строка JSON, определенная как переменная s1 :
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34
}
}
И мы хотим сравнить его с другим JSON, s2
:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles"
}
}
Давайте прочитаем входной JSON как JsonNode
и сравним:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
Важно отметить, что хотя порядок атрибутов во входных переменных JSON s1
и s2
не одинаков, метод equals()
игнорирует порядок и рассматривает их как равные.
3.2. Сравните два объекта JSON с вложенным элементом
Далее мы увидим, как сравнить два объекта JSON с вложенными элементами.
Начнем с JSON, определенного как переменная s1 :
{
"employee":
{
"id": "1212",
"fullName":"John Miles",
"age": 34,
"contact":
{
"email": "john@xyz.com",
"phone": "9999999999"
}
}
}
Как мы видим, JSON содержит вложенный элемент contact
. Мы хотим сравнить его с другим JSON, определенным s2
:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"contact":
{
"email": "john@xyz.com",
"phone": "9999999999"
}
}
}
Давайте прочитаем входной JSON как JsonNode
и сравним:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
Опять же, мы должны заметить, что equals()
также может сравнивать два входных объекта JSON с вложенными элементами.
3.3. Сравните два объекта JSON, содержащие элемент списка
Точно так же мы можем сравнить два объекта JSON, которые содержат элемент списка.
Давайте рассмотрим этот JSON, определенный как s1
:
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34,
"skills": ["Java", "C++", "Python"]
}
}
Мы сравниваем его с другим JSON s2
:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"skills": ["Java", "C++", "Python"]
}
}
Давайте прочитаем входной JSON как JsonNode
и сравним:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
Важно знать, что два элемента списка сравниваются как равные только в том случае, если они имеют одинаковые значения в одном и том же порядке.
4. Сравните два объекта JSON с помощью пользовательского компаратора
JsonNode.equals
работает достаточно хорошо в большинстве случаев. Джексон также предоставляет JsonNode.equals(comparator, JsonNode)
для
настройки собственного объекта компаратора Java. Давайте разберемся, как использовать пользовательский Comparator
.
4.1. Пользовательский компаратор для сравнения числовых значений
Давайте разберемся, как использовать пользовательский компаратор
для сравнения двух элементов JSON, имеющих числовые значения.
Мы будем использовать этот JSON в качестве ввода s1
:
{
"name": "John",
"score": 5.0
}
Давайте сравним с другим JSON, определенным как s2
:
{
"name": "John",
"score": 5
}
Мы должны заметить, что значения оценки
атрибута во входных данных s1
и s2
не совпадают.
``
Давайте прочитаем входной JSON как JsonNode
и сравним:
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
assertNotEquals(actualObj1, actualObj2);
Как мы можем заметить, два объекта не равны. Стандартный метод equals()
считает значения 5.0 и 5 разными.
Однако мы можем использовать пользовательский компаратор
для сравнения значений 5 и 5.0 и рассматривать их как равные .
Давайте сначала создадим Comparator
для сравнения двух объектов NumericNode
:
public class NumericNodeComparator implements Comparator<JsonNode>
{
@Override
public int compare(JsonNode o1, JsonNode o2)
{
if (o1.equals(o2)){
return 0;
}
if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)){
Double d1 = ((NumericNode) o1).asDouble();
Double d2 = ((NumericNode) o2).asDouble();
if (d1.compareTo(d2) == 0) {
return 0;
}
}
return 1;
}
}
Далее давайте посмотрим, как использовать этот Comparator
:
NumericNodeComparator cmp = new NumericNodeComparator();
assertTrue(actualObj1.equals(cmp, actualObj2));
4.2. Пользовательский компаратор для сравнения текстовых значений
Давайте посмотрим на другой пример пользовательского компаратора
для сравнения двух значений JSON без учета регистра.
Мы будем использовать этот JSON в качестве ввода s1
:
{
"name": "john",
"score": 5
}
Давайте сравним с другим JSON, определенным как s2
:
{
"name": "JOHN",
"score": 5
}
Как мы видим, имя
атрибута пишется строчными буквами в поле ввода s1
и прописными буквами в поле s2
.
Давайте сначала создадим Comparator
для сравнения двух объектов TextNode
:
public class TextNodeComparator implements Comparator<JsonNode>
{
@Override
public int compare(JsonNode o1, JsonNode o2) {
if (o1.equals(o2)) {
return 0;
}
if ((o1 instanceof TextNode) && (o2 instanceof TextNode)) {
String s1 = ((TextNode) o1).asText();
String s2 = ((TextNode) o2).asText();
if (s1.equalsIgnoreCase(s2)) {
return 0;
}
}
return 1;
}
}
Давайте посмотрим, как сравнить s1
и s2
с помощью TextNodeComparator:
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
TextNodeComparator cmp = new TextNodeComparator();
assertNotEquals(actualObj1, actualObj2);
assertTrue(actualObj1.equals(cmp, actualObj2));
Наконец, мы можем видеть, что использование пользовательского объекта сравнения при сравнении двух объектов JSON может быть очень полезным, когда значение входного элемента JSON не совсем одинаково, но мы по-прежнему хотим рассматривать их как равные.
5. Вывод
В этом кратком руководстве мы увидели, как использовать Jackson для сравнения двух объектов JSON и использовать собственный компаратор .
Конечно, как всегда, полный исходный код всех обсуждаемых здесь примеров можно найти на GitHub .