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

Обновлено: 06.07.2024

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 аттачей.

Как я могу проверить, равны ли два объекта JSON в python, не обращая внимания на порядок списков?

Документ JSON a :

Документ JSON b :

a и b должны сравниваться одинаково, даже если порядок в "errors" списках разный.

Почему бы просто не расшифровать их и не сравнить? Или вы имеете в виду, что порядок «массива» или list элементов тоже не имеет значения? Прошу простить мою наивность, но почему? Элементы списка имеют определенный порядок не зря.

Если вы хотите, чтобы два объекта с одинаковыми элементами, но в разном порядке сравнивали равные, то очевидное дело - сравнить их отсортированные копии - например, для словарей, представленных вашими строками JSON a и b :

. но это не работает, потому что в каждом случае "errors" элемент dict верхнего уровня представляет собой список с одинаковыми элементами в другом порядке и sorted() не пытается отсортировать что-либо, кроме «верхнего» уровня итеративный.

Если мы применим эту функцию к a и b , результаты будут равны:

Большое вам спасибо Zero Piraeus. это именно то общее решение, которое мне нужно. но единственная проблема в том, что код работает только для python 2.x, а не для python3. Я получаю следующую ошибку: TypeError: unorderable types: dict () <dict () В любом случае решение теперь ясно. Я постараюсь заставить его работать на python3. Большое спасибо когда есть список вроде ['astr', <'adict': 'something'>] , я получил TypeError при попытке их отсортировать. @ Blairg23, вы неправильно поняли вопрос, который касается сравнения объектов JSON как равных, когда они содержат списки, элементы которых одинаковы, но в другом порядке, а не о каком-либо предполагаемом порядке словарей.

Другой способ - использовать json.dumps(X, sort_keys=True) опцию:

Это работает для вложенных словарей и списков.

<"error":"a">, против, , <"error":"a">он не сможет отсортировать последний случай в первый случай @ Blairg23, а что бы вы сделали, если бы у вас были списки, вложенные в dict? Вы не можете просто сравнить диктат верхнего уровня и назвать это днем, это не то, о чем этот вопрос. Это не работает, если у вас есть списки внутри. например json.dumps(<'foo': [3, 1, 2]>, sort_keys=True) == json.dumps(<'foo': [2, 1, 3]>, sort_keys=True) @ Данил и, наверное, не должно. Списки представляют собой упорядоченную структуру, и если они отличаются только порядком, мы должны считать их разными. Возможно, для вашего варианта использования порядок не имеет значения, но мы не должны этого предполагать. поскольку списки упорядочены по индексу, они не будут пересортированы. [0, 1] не должно равняться [1, 0] в большинстве ситуаций. Так что это хорошее решение для обычного случая, но не для вопроса выше. все еще +1

Расшифруйте их и сравните как комментарий mgilson.

Порядок не имеет значения для словаря, пока ключи и значения совпадают. (Словарь не имеет порядка в Python)

Но порядок важен в списке; сортировка решит проблему для списков.

Приведенный выше пример будет работать для JSON в вопросе. Для общего решения см. Ответ Zero Piraeus.

Для следующих двух dictWithListsInValue и reorderedDictWithReorderedListsInValue, которые представляют собой просто переупорядоченные версии друг друга.

дал мне неправильный результат, т.е. ложный.

Итак, я создал свой собственный компаратор объектов Cutstom вот так:

что дало мне правильный ожидаемый результат!

Логика довольно проста:

Если объекты относятся к типу «список», тогда сравнивайте каждый элемент первого списка с элементами второго списка до тех пор, пока он не будет найден, и если элемент не будет найден после просмотра второго списка, тогда «найденный» будет = false. возвращается значение 'found'

В противном случае, если сравниваемые объекты относятся к типу «dict», сравните значения, представленные для всех соответствующих ключей в обоих объектах. (Выполняется рекурсивное сравнение)

В противном случае просто вызовите obj1 == obj2. По умолчанию он отлично работает для объекта строк и чисел, и для них eq () определен соответствующим образом.

(Обратите внимание, что алгоритм можно дополнительно улучшить, удалив элементы, найденные в объекте 2, чтобы следующий элемент объекта 1 не сравнивался с элементами, уже найденными в объекте 2)

В некоторых случаях сравните два json / dictionary, возможно, этого можно добиться:

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

Есть такая библиотека, которая может решить эту проблему, этоjson_tools

установка

Сравнить json

Во-первых, давайте взглянем на атрибуты или методы и воспользуемся универсальной лабораторией, чтобы увидеть:

[‘builtins’, ‘doc’, ‘file’, ‘loader’, ‘name’, ‘package’, ‘path’, ‘_patch_main’, ‘_printer_main’, ‘diff’, ‘patch’, ‘path’, ‘print_function’, ‘print_json’, ‘print_style’, ‘printer’]

Из приведенных выше результатов вы можете увидеть json_tools Различные свойства и методы.

Я использовал diff в проекте, давайте продемонстрируем процесс

Приведенное выше сравнение относительно простое, оно показывает изменение b относительно a, обратите особое внимание, если это b относительно a, напишите так: json_tools.diff(a,b) ,если json_tools.diff(b,a) , Будет отличаться от приведенного выше, посмотрите результат:

Чтобы json_tools(a,b) , То есть изменение b относительно a в качестве примера.

  • б и а имеют ключи 'a' , Но b относительно a, ключ 'a' Изменилось с оригинала 1 , Становится 2 . Итак, в списке результатов сравнения есть элемент, который отражает этот результат. , Где replace представляет измененный ключ, value представляет текущее значение ключа после изменения, а prev представляет предыдущее значение ключа.
  • в б 'c' По отношению к a это новый ключ. Итак, результат сравнения отражает следующее:
  • b не относительно a 'b' Этот ключ, который удален в b, отображается в результате сравнения следующим образом:

С помощью приведенных выше результатов отображаются не только подробные результаты сравнения, но и сравнение многоуровневого вложенного json. Например:

Вот отношения вложенности измененного ключа. Такие как '/a/aa/aaa2' , Это означает >> Стоимость изменилась.

Вот вложенная строка ключа. На практике иногда бывает необходимо преобразовать строку в формат json, а именно превратиться в >> 。

Собирать строки в формат json

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

Однако я ленивый программист, и причина, по которой я предпочитаю python, заключается в том, что он позволяет мне быть ленивым.

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

По существу; "если какие-либо email (ы) в emails_exist появляются в emails_all, не включайте их как часть emails_new"

Существующие Массивы

Удалив все значения emails_exist из emails_all , я хочу только построить список, чтобы показать email/first_name писем, которые не появляются в emails_exist . как показано ниже emails_new

Выход

Возможно, стоит отметить: эти массивы JSON могут содержать до 100 элементов в каждом.

2 ответа

Просто используйте простую вспомогательную функцию

@Danny , вы также можете получить ожидаемый результат всего с 1 строкой кода , используя функции Python , map() , filter(), lambda и т. Д., Как показано в приведенных ниже примерах кода.

Пожалуйста, прокомментируйте, если у вас возникнут какие-либо проблемы при чтении & понимание моего кода.

Проверьте Lambda, filter(), map() и понимание списка . Очень хорошо использовать эти концепции в программировании.

1 код строки

Теперь взгляните на приведенные ниже примеры кода один за другим.

Пример 1

Пример 2

Похожие вопросы:

У меня возникла проблема со сравнением двух массивов. Один представляет собой фиксированный набор данных, в то время как другой генерируется динамически. Пример этих двух массивов выглядит следующим.

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

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

Я работаю над веб-сайтом, использующим Xbox API, который возвращает игровую информацию для данного пользователя. Он возвращает результаты в формате json: < Data: < Gamertag: Major Nelson, Gamerpic.

У меня есть два массива из двух разных объектов объект 1 : Class partner < var pImage: String? var pTimeStamp: NSDate? var pTitle: String? var ID: String? >объект 2 : Class customer < var cImage.

Моя проблема заключается в сравнении значений двух разных массивов, не для того, чтобы знать, равны ли они, но если значение в массиве A существует в массиве B. Includes не работает, и я не.

Я пытаюсь умножить каждый элемент из двух разных массивов. Я имею в виду, что у меня есть array1 = [i1 , i2] и array2 = [j1, j2] , поэтому мне нужно сделать (i1 * j1) + (i2 * j2) . Как я могу.

Хорошо ли определено сравнение двух символов (то есть одного символа str ) в Python (3.x, если это имеет значение)? или я должен сделать явное преобразование? Другими словами, это: 'a' > 'b' то.

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