¿Cómo puedo probar si dos objetos JSON son iguales en Python, sin tener en cuenta el orden de las listas?
Por ejemplo ...
Documento JSON a :
{
"errors": [
{"error": "invalid", "field": "email"},
{"error": "required", "field": "name"}
],
"success": false
}
Documento JSON b :
{
"success": false,
"errors": [
{"error": "required", "field": "name"},
{"error": "invalid", "field": "email"}
]
}
a
y b
deben comparar iguales, aunque el orden de las "errors"
listas sea diferente.
python
json
django
comparison
Petter Friberg
fuente
fuente
list
elementos tampoco importa?Respuestas:
Si desea que dos objetos con los mismos elementos pero en un orden diferente se comparen iguales, lo obvio es comparar copias ordenadas de ellos, por ejemplo, para los diccionarios representados por sus cadenas JSON
a
yb
:... pero eso no funciona, porque en cada caso, el
"errors"
elemento del dict de nivel superior es una lista con los mismos elementos en un orden diferente, ysorted()
no intenta ordenar nada excepto el nivel "superior" de un iterable.Para solucionarlo, podemos definir una
ordered
función que ordenará de forma recursiva cualquier lista que encuentre (y convertirá los diccionarios en listas de(key, value)
pares para que se puedan ordenar):Si aplicamos esta función a
a
yb
, los resultados son iguales:fuente
['astr', {'adict': 'something'}]
, obtuveTypeError
al intentar ordenarlos.Otra forma podría ser usar la
json.dumps(X, sort_keys=True)
opción:Esto funciona para diccionarios y listas anidados.
fuente
{"error":"a"}, {"error":"b"}
vs{"error":"b"}, {"error":"a"}
no podrá clasificar el último caso en el primer casojson.dumps({'foo': [3, 1, 2]}, sort_keys=True) == json.dumps({'foo': [2, 1, 3]}, sort_keys=True)
Decodifíquelos y compárelos como comentario mgilson.
El orden no importa para el diccionario siempre que las claves y los valores coincidan. (El diccionario no tiene orden en Python)
Pero el orden es importante en la lista; ordenar resolverá el problema de las listas.
El ejemplo anterior funcionará para JSON en la pregunta. Para una solución general, consulte la respuesta de Zero Piraeus.
fuente
Para los siguientes dos dicts 'dictWithListsInValue' y 'reorderedDictWithReorderedListsInValue', que son simplemente versiones reordenadas entre sí
me dio un resultado incorrecto, es decir, falso.
Así que creé mi propio ObjectComparator cutstom así:
lo que me dio el resultado esperado correcto!
La lógica es bastante simple:
Si los objetos son del tipo 'lista', compare cada elemento de la primera lista con los elementos de la segunda lista hasta que los encuentre, y si el elemento no se encuentra después de pasar por la segunda lista, entonces 'encontrado' sería = falso. se devuelve el valor 'encontrado'
De lo contrario, si los objetos a comparar son de tipo 'dict', compare los valores presentes para todas las claves respectivas en ambos objetos. (Se realiza una comparación recursiva)
De lo contrario, simplemente llame a obj1 == obj2. De forma predeterminada, funciona bien para el objeto de cadenas y números y para esos eq () se define adecuadamente.
(Tenga en cuenta que el algoritmo se puede mejorar aún más eliminando los elementos que se encuentran en object2, de modo que el siguiente elemento de object1 no se compare con los elementos que ya se encuentran en el object2)
fuente
Puedes escribir tu propia función igual:
a == b
Debido a que usted está tratando con JSON, tendrá tipos estándar de Python:
dict
,list
, etc, por lo que puede hacer la comprobación de tipos duroif type(obj) == 'dict':
, etc.Ejemplo aproximado (no probado):
fuente
Para aquellos que deseen depurar los dos objetos JSON (generalmente, hay una referencia y un objetivo ), aquí hay una solución que puede usar. Enumerará la " ruta " de los diferentes / no coincidentes desde el objetivo hasta la referencia.
level
La opción se utiliza para seleccionar la profundidad a la que le gustaría mirar.show_variables
La opción se puede activar para mostrar la variable relevante.fuente