Рубрики
Без рубрики

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

Узнайте, как использовать Jackson для сравнения двух объектов JSON с помощью встроенного компаратора и пользовательского компаратора

Автор оригинала: baeldung.

1. Обзор

В этой статье мы рассмотрим сравнение двух объектов JSON с использованием Jackson – библиотеки обработки JSON для Java.

2. Зависимость Maven

Во-первых, давайте добавим зависимость jackson-databind |/Maven:


    com.fasterxml.jackson.core
    jackson-databind
    2.11.1

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": "[email protected]",
            "phone": "9999999999"
        }
    }
}

Как мы видим, JSON содержит вложенный элемент contact . Мы хотим сравнить его с другим JSON, определенным s2 :

{
    "employee":
    {
        "id": "1212",
        "age": 34,
        "fullName": "John Miles",
        "contact":
        {
            "email": "[email protected]",
            "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 C 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 и рассматривать их как равные .

Давайте сначала создадим Компаратор для сравнения двух Числовых узлов объектов:

public class NumericNodeComparator implements Comparator 
{
    @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;
    }
}

Далее давайте посмотрим, как использовать этот Компаратор :

NumericNodeComparator cmp = new NumericNodeComparator();
assertTrue(actualObj1.equals(cmp, actualObj2));

4.2. Пользовательский компаратор для сравнения текстовых значений

Давайте рассмотрим другой пример пользовательского компаратора для сравнения двух значений JSON без учета регистра.

Мы будем использовать этот JSON в качестве входных данных s1 :

{
    "name": "john", 
    "score": 5 
}

Давайте сравним с другим JSON, определенным как s2 :

{ 
    "name": "JOHN", 
    "score": 5 
}

Как мы видим, атрибут name является строчным в input s1 и прописным в s2 .

Давайте сначала создадим Компаратор для сравнения двух текстовых узлов объектов:

public class TextNodeComparator implements Comparator 
{
    @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 с помощью Компаратор текстовых узлов:

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. Заключение

В этом кратком руководстве мы рассмотрели, как использовать Джексона для сравнения двух объектов JSON и использовать пользовательский компаратор .

Конечно, как всегда, полный исходный код всех примеров, обсуждаемых здесь, можно найти на GitHub .