Перейти к основному содержимому

Сравните два объекта JSON с Джексоном

· 5 мин. чтения

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 .