Сравнить два json файла

Обновлено: 01.07.2024

Я ищу библиотеку синтаксического анализа JSON, которая поддерживает сравнение двух объектов JSON, игнорирующих дочерний порядок, в частности для модульного тестирования JSON, возвращающегося из веб-службы.

поддерживает ли это какая-либо из основных библиотек JSON? Организация.библиотека json просто выполняет сравнение ссылок.

в качестве общей архитектурной точки я обычно не советую позволять зависимостям от определенного формата сериализации истекать за пределы вашего уровня хранения / сети; таким образом, я бы сначала рекомендовал вам рассмотреть возможность тестирования равенства между вашими собственными объектами приложения, а не их проявлениями JSON.

сказав это, я в настоящее время большой поклонник Джексон который мой быстрый чтение их ObjectNode.equals () реализация предполагает, что установите сравнение членства, которое вы хотите:

попробовать Skyscreamer это JSONAssert.

его нестрогом режим имеет два основных преимущества, которые делают его менее хрупким:

  • расширяемость объекта (например, с ожидаемым значением , это все равно пройдет: .)
  • порядок свободных массивов (например, ['dog', 'cat']==['cat','dog'])

в строгом режиме он ведет себя больше как тест json-lib класс.

тест выглядит примерно так:

параметры в JSONAssert.assertEquals() вызову expectedJSONString, actualDataString и isStrict.

Я бы сделал следующее,

вы можете попробовать использовать JSON-lib JSONAssert класс:

если вы уже используете JUnit, последняя версия теперь использует Hamcrest. Это общая структура сопоставления (особенно полезная для модульного тестирования), которая может быть расширена для создания новых сопоставителей.

есть небольшая библиотека с открытым исходным кодом под названием hamcrest-json с совпадениями JSON-aware. Он хорошо документирован, протестирован и поддерживается. Ниже приведены некоторые полезные ссылки:

пример кода с использованием объектов из библиотеки JSON org.json.simple :

дополнительно вы можете (1) разрешить массивы "любого порядка" и (2) игнорировать дополнительные поля.

поскольку существует множество библиотек JSON для Java ( Jackson , GSON , json-lib , etc.), полезно, что hamcrest-json поддерживает текст JSON (as java.lang.String ), а также изначально поддерживающие объекты из JSON Дугласа Крокфорда библиотека org.json .

наконец, если вы не используете JUnit, вы можете использовать Hamcrest непосредственно для утверждений. (я писал об этом здесь.)

JsonUnit хорошая библиотека для сравнения двух json

Как сравнить два больших json и получить allure-attachment в читаемом виде? В этом нам поможет JsonUnit

Чем нравится

  1. Работает с json как с деревом типизированных элементов. Из-за этого имеет множество полезных возможностей:
    • Игнорирование null элементов
    • Игнорирование порядка в массиве
    • Игнорирование новых элементов в массиве
    • Игнорирование новых полей
    • Игнорирование значений всех полей
    • Игнорирование значений определенных полей
  2. Возможность использования как в виде статичного метода, так в виде Hamcrest matcher-а, Spring MVC assertions и fluent assertions.
  3. Также есть возможность сравнивать с json, имееющую различные placeholder-ы:
    • $ для игнориварония элементов
    • $ для сравнения с регулярным выражением
    • $ , , для типов
    • $ для своих кастомных матчеров
  4. Проект развивается. Например недавно добавилась интеграция с assertJ (beta). Также еще много других интересных фич, о которых можно почитать в README.md

Чем не нравится

На данный момент, на мой взгляд, есть несколько недостатков:

  1. Библиотека не умеет определять перемещение элементов в массиве. Только добавление/удаление и изменение.
  2. Неудобное игнорирование значений полей (не по json path).
  3. Почти нет точек расширения. Например, классно было бы добавить возможность сравнения всех строк определенным образом, игнорируя что-то по регулярному выражению.

Есть и еще один недостаток, jsonUnit из коробки выкидывает diff в консоль в не очень читаемом виде. Для больших json при наличии большого количества отличий визуально непонятно, чем они отличаются. Именно поэтому для своих тестов я сделал интеграцию с allure.

Интеграция с allure

Я добавил обобщенный diff и сделал возможность добавления своего кастомного listener-а в jsonUnit. Таким образом достаточно для каждого теста в lister-е получить абстактный diff, привести к требуемому формату, а после ‘отрендерить’ его в красивую html-ку и прекрепить его к отчету через механизм allure аттачей.

А вот ещё один JavaScript-овый объект, тоже сериализованный в JSon:

У них одинаковая структура, одинаковые параметры, одинаковые значения в этих параметрах. По всем признакам, и в source1 , и в source2 у нас одно и то же.

Но интерпретатор JavaScript с нами, разумеется, не согласен. И он вполне резонно считает, что source1 и source2 — разные строки. А если мы десериализуем их обратно, то получим два object-а, которые расположены по различным адресам памяти и… тоже не равны друг другу.

А если вы, впридачу, работает с Ext.js, щедро генерируете свои классы и не забываете про jSon, то может дойти до полного затмения. Как сравнить эти огромные простыни сведений о контролах, которые собираются в JSon-ы? Или разобраться древовидными объектами, где в каждое поле уже успели насоздаваться ещё какие-то подполя?

Выход один — нужно найти способ сравнивать не по значению, не по ячейке в памяти, а более гибко. Равными должны считаться те объекты, у которых одинаковые поля содержат одинаковые значения. С этой точки зрения наш source1 безусловно равен source2 .

Так и родился на свет очередной велосипед — JSonCmp. Простая, и очень нужная функция для сравнения объектов в JavaScript. Разумеется, я находил много попыток написать такую, но каждая из реализаций решала только часть проблемы — в итоге я свёл все интересные идеи в одну, попутно добавив пару своих…

Использовать его просто — достаточно подключить jsoncmp.js, и потом вызвать:

Если объекты содержат одну и ту же информацию, функция вернёт true. Иначе — false.

Пользователи Ext.js могут использовать тот же самый алгоритм, но в обёртке плагина — jsoncmp.ext.js. Код будет выглядеть так:

  • null равен null
  • объекты разных типов не равны
  • переменная по значению (Float, Integer, Boolean) сравнивается по значению
  • строки сравниваются по значению
  • сериализованные JSon-ы сравниваются как десериализованные объекты
  • функции сравниваются по исходному коду, приведённому к string
  • объекты jQuery сравниваются через стандартную для этой библиотеки функцию is
  • объекты сравниваются по полям и их значениям. Если в значении поля тоже объект — он сравнивается по тому же принципу
  • если при обходе этого дерева обнаруживается, что лист ссылается на один из уже пройденных объектов (это означает, что в дереве есть цикл) — будут сравниваться ссылки на объекты".
  • массивы сравниваются и на соответствие элементов, и на их очерёдность
  • если выставить в настройках поиска arraysAsSets = true, то массивы будут восприниматься как множества (set-ы) и очерёдность элементов будет игнорироваться. Настройки поиска выставляются в третьем, необязательном параметре. Вот таким образом:

Я надеюсь, что это небольшая и наверняка несовершенная функция чуть-чуть, но упростит вашу работу.

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

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

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

3. Использование Джексона для сравнения двух объектов JSON

Мы будем использовать класс ObjectMapper для чтения объекта как JsonNode.

Давайте создадим ObjectMapper :

3.1. Сравните Два Простых Объекта JSON

Давайте начнем с использования метода JsonNode.equals . Метод equals() выполняет полное (глубокое) сравнение.

Предположим, у нас есть строка JSON, определенная как переменная s1 :

И мы хотим сравнить его с другим JSON, s2 :

Давайте прочитаем входной JSON как JsonNode и сравним:

Важно отметить, что несмотря на то, что порядок атрибутов во входных переменных JSON s1 и s2 не совпадает, метод equals() игнорирует порядок и рассматривает их как равные.

3.2. Сравните два объекта JSON с вложенным элементом

Далее мы рассмотрим, как сравнить два объекта JSON, имеющих вложенные элементы.

Давайте начнем с JSON, определенного как переменная s1 :

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

Давайте прочитаем входной JSON как JsonNode и сравним:

Опять же, мы должны заметить, что equals() также может сравнивать два входных объекта JSON с вложенными элементами.

3.3. Сравните два объекта JSON, Содержащих элемент списка

Аналогично, мы также можем сравнить два объекта JSON, которые содержат элемент списка.

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

Мы сравниваем его с другим JSON s2 :

Давайте прочитаем входной JSON как JsonNode и сравним:

Важно знать, что два элемента списка сравниваются как равные только в том случае, если они имеют одинаковые значения в одном и том же порядке.

4. Сравните два объекта JSON с помощью пользовательского компаратора

JsonNode.equals работает довольно хорошо в большинстве случаев. Джексон также предоставляет JsonNode.equals(comparator, JsonNode) для настройки пользовательского объекта Java C comparator . Давайте разберемся, как использовать пользовательский Компаратор .

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

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

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

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

Мы должны заметить, что значения атрибута оценка во входных данных s1 и s2 не совпадают.

Давайте прочитаем входной JSON как JsonNode и сравним:

Как мы можем заметить, эти два объекта не равны. Стандартный метод equals() рассматривает значения 5.0 и 5 как разные.

Однако мы можем использовать пользовательский компаратор для сравнения значений 5 и 5.0 и рассматривать их как равные .

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

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

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

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

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

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

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

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

Давайте посмотрим, как сравнить s1 и s2 с помощью Компаратор текстовых узлов:

Наконец, мы видим, что использование пользовательского объекта компаратора при сравнении двух объектов JSON может быть очень полезно, когда входное значение элемента JSON не совсем совпадает, но мы все равно хотим рассматривать их как равные.

5. Заключение

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

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

Лучший способ сравнить 2 файла JSON в Java

BIM + Виртуальная реальность - игровой дизайн для взаимодействия с людьми

Как вы посоветуете подойти к этой задаче?

На мой взгляд, проблема состоит в том, чтобы грамотно представить различную информацию. Прежде чем я изобрету велосипед, есть ли общепринятый подход к такому сравнению?

  • 2 В этом ответе вы найдете решение с Джексоном / Гсоном и Гуавой.

Вы можете попробовать архитектуру XStream, обработку сопоставлений JSON

Я рекомендую библиотеку zjsonpatch, которая представляет информацию о различиях в соответствии с RFC 6902 (JSON Patch). Вы можете использовать это с Джексоном:

  • 1 Это только сравнение структуры документов json.
  • 2 Его сравнение ключей и значений. Как сделать это только для ключей?
  • Код у меня не работал. Вероятно, вам нужно сделать новый ObjectMapper первый: java ObjectMapper mapper = new ObjectMapper(); JsonNode beforeNode = jacksonObjectMapper.readTree(beforeJsonString); JsonNode afterNode = jacksonObjectMapper.readTree(afterJsonString); JsonNode patch = JsonDiff.asJson(beforeNode, afterNode); String diffs = patch.toString();

Я получил хороший опыт работы с JSONAssert.

Это касается только равенства, а не различий.

Из JavaDoc для JsonNode.equals:

Равенство для узловых объектов определяется как полное (глубокое) равенство значений. Это означает, что можно сравнивать полные деревья JSON на равенство, сравнивая равенство корневых узлов.

  • 6 mapper.readTree не работает, если json-поля имеют другой порядок.
  • 1 И сравнивает только структуру json-документов.
  • Его сравнение ключей и значений. Как сделать это только для ключей?
  • @EanV, а также Черри неправда. он сравнивает значения и даже если члены вышли из строя ..

Самый простой способ сравнить строки json - использовать JSONCompare из библиотеки JSONAssert. Преимущество в том, что он не ограничивается только структурой и может сравнивать значения, если хотите:

что выведет что-то вроде:

У меня была аналогичная проблема, и я написал свою собственную библиотеку:

Он выполняет как изменение, так и исправление.

Различия сами по себе являются JSON-объектами и имеют простой синтаксис для слияния / замены объектов и вставки / замены массива.

указывает на слияние объектов.

  • Ограничивается только структурой документов.
  • 1 шт. он тоже сравнивает значения. но я не рекомендую его использовать, так как я столкнулся с трудно решаемыми крайними случаями и потерял интерес.

json-lib

Что бы я сделал, так это проанализировать данные json с помощью json-lib. Это приведет к созданию обычных java-объектов, которые вы можете сравнивать с помощью методов equals. Это действительно только предполагая ребята из json-lib правильно реализовали метод equals, но это вы легко можете проверить.

Старший, это мое решение для Java-кода поверх моего приложения;

Надеюсь, что это поможет другим, конечно. Просто укажите свои ценности, условия и вид взгляда в этом случае; Hashmap поверх списка.

Для людей, которые уже используют Джексон, Я рекомендую json-patch

  • Я зашел на их сайт и обнаружил, что он под лицензией LGPLv3.поправьте меня, если я ошибаюсь, но разве LGPL не ограничивает использование корпораций?

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

Читайте также: