Wie kann ich testen, ob zwei JSON-Objekte in Python gleich sind, ohne die Reihenfolge der Listen zu berücksichtigen?
Zum Beispiel ...
JSON-Dokument a :
{
"errors": [
{"error": "invalid", "field": "email"},
{"error": "required", "field": "name"}
],
"success": false
}
JSON-Dokument b :
{
"success": false,
"errors": [
{"error": "required", "field": "name"},
{"error": "invalid", "field": "email"}
]
}
a
und b
sollte gleich vergleichen, obwohl die Reihenfolge der "errors"
Listen unterschiedlich ist.
python
json
django
comparison
Petter Friberg
quelle
quelle
list
Elemente auch keine Rolle spielt?Antworten:
Wenn Sie möchten, dass zwei Objekte mit denselben Elementen in einer anderen Reihenfolge gleich verglichen werden, müssen Sie natürlich sortierte Kopien davon vergleichen - beispielsweise für die Wörterbücher, die durch Ihre JSON-Zeichenfolgen dargestellt werden,
a
undb
:... aber das funktioniert nicht, denn in jedem Fall ist das
"errors"
Element des Diktats der obersten Ebene eine Liste mit denselben Elementen in einer anderen Reihenfolge undsorted()
versucht nur, die "oberste" Ebene von zu sortieren eine iterable.Um dies zu beheben, können wir eine
ordered
Funktion definieren , die alle gefundenen Listen rekursiv sortiert (und Wörterbücher in Listen von(key, value)
Paaren konvertiert, damit sie geordnet werden können):Wenn wir diese Funktion auf
a
und anwendenb
, sind die Ergebnisse gleich:quelle
['astr', {'adict': 'something'}]
, habe ichTypeError
beim Versuch, sie zu sortieren.Eine andere Möglichkeit könnte darin bestehen, die
json.dumps(X, sort_keys=True)
Option zu verwenden :Dies funktioniert für verschachtelte Wörterbücher und Listen.
quelle
{"error":"a"}, {"error":"b"}
vs{"error":"b"}, {"error":"a"}
es wird nicht in der Lage sein, den letzteren Fall in den ersten Fall zu sortierenjson.dumps({'foo': [3, 1, 2]}, sort_keys=True) == json.dumps({'foo': [2, 1, 3]}, sort_keys=True)
Dekodiere sie und vergleiche sie als mgilson-Kommentar.
Die Reihenfolge spielt für das Wörterbuch keine Rolle, solange die Schlüssel und Werte übereinstimmen. (Wörterbuch hat keine Reihenfolge in Python)
Aber die Reihenfolge ist wichtig in der Liste; Durch Sortieren wird das Problem für die Listen gelöst.
Das obige Beispiel funktioniert für den JSON in der Frage. Eine allgemeine Lösung finden Sie in der Antwort von Zero Piraeus.
quelle
Für die folgenden zwei Diktate 'dictWithListsInValue' und 'reorderedDictWithReorderedListsInValue', die einfach neu geordnete Versionen voneinander sind
gab mir falsches Ergebnis dh falsch.
Also habe ich meinen eigenen cutstom ObjectComparator wie folgt erstellt:
das gab mir die richtige erwartete Ausgabe!
Logik ist ziemlich einfach:
Wenn die Objekte vom Typ 'Liste' sind, vergleichen Sie jedes Element der ersten Liste mit den Elementen der zweiten Liste, bis sie gefunden werden. Wenn das Element nach Durchlaufen der zweiten Liste nicht gefunden wird, ist 'gefunden' = falsch. Der Wert 'found' wird zurückgegeben
Andernfalls vergleichen Sie die Werte, die für alle jeweiligen Schlüssel in beiden Objekten vorhanden sind, wenn die zu vergleichenden Objekte vom Typ 'dict' sind. (Rekursiver Vergleich wird durchgeführt)
Andernfalls rufen Sie einfach obj1 == obj2 auf. Es funktioniert standardmäßig gut für das Objekt von Zeichenfolgen und Zahlen und für diese ist eq () entsprechend definiert.
(Beachten Sie, dass der Algorithmus weiter verbessert werden kann, indem die in Objekt2 gefundenen Elemente entfernt werden, sodass sich das nächste Element von Objekt1 nicht mit den bereits in Objekt2 gefundenen Elementen vergleicht.)
quelle
Sie können Ihre eigene Gleichheitsfunktion schreiben:
a == b
Weil Sie mit json zu tun hat , werden Sie Standard - Python - Typen haben:
dict
,list
etc., so dass Sie hart Typprüfung tun könnenif type(obj) == 'dict':
, usw.Grobes Beispiel (nicht getestet):
quelle
Für andere, die die beiden JSON-Objekte debuggen möchten (normalerweise gibt es eine Referenz und ein Ziel ), ist hier eine Lösung, die Sie verwenden können. Es wird der " Pfad " verschiedener / nicht übereinstimmender vom Ziel zur Referenz aufgelistet.
level
Mit dieser Option können Sie auswählen, in welche Tiefe Sie schauen möchten.show_variables
Option kann aktiviert werden, um die relevante Variable anzuzeigen.quelle