Como posso testar se dois objetos JSON são iguais em python, desconsiderando a ordem das listas?
Por exemplo ...
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
e b
deve comparar iguais, embora a ordem das "errors"
listas seja diferente.
python
json
django
comparison
Petter Friberg
fonte
fonte
list
elementos também não importa?Respostas:
Se você deseja dois objetos com os mesmos elementos, mas em uma ordem diferente para comparar iguais, a coisa óbvia a fazer é comparar as cópias ordenadas deles - por exemplo, para os dicionários representados por suas strings JSON
a
eb
:... mas isso não funciona, porque em cada caso, o
"errors"
item do dict de nível superior é uma lista com os mesmos elementos em uma ordem diferente esorted()
não tenta classificar nada, exceto o nível "superior" de um iterável.Para corrigir isso, podemos definir uma
ordered
função que classificará recursivamente todas as listas que encontrar (e converterá dicionários em listas de(key, value)
pares para que sejam ordenáveis):Se aplicarmos esta função a
a
eb
, os resultados serão iguais:fonte
['astr', {'adict': 'something'}]
, eu receboTypeError
ao tentar classificá-los.Outra forma poderia ser usar a
json.dumps(X, sort_keys=True)
opção:Isso funciona para listas e dicionários aninhados.
fonte
{"error":"a"}, {"error":"b"}
vs{"error":"b"}, {"error":"a"}
não será capaz de classificar o último caso no primeiro casojson.dumps({'foo': [3, 1, 2]}, sort_keys=True) == json.dumps({'foo': [2, 1, 3]}, sort_keys=True)
Decodifique-os e compare-os como comentário do mgilson.
A ordem não importa para o dicionário, desde que as chaves e os valores correspondam. (O dicionário não tem ordem em Python)
Mas a ordem é importante na lista; a classificação resolverá o problema das listas.
O exemplo acima funcionará para o JSON em questão. Para uma solução geral, consulte a resposta de Zero Piraeus.
fonte
Para os dois dictes a seguir 'dictWithListsInValue' e 'reorderedDictWithReorderedListsInValue', que são simplesmente versões reordenadas um do outro
me deu resultado errado, ou seja, falso.
Então, criei meu próprio ObjectComparator cutstom assim:
que me deu a saída esperada correta!
A lógica é muito simples:
Se os objetos forem do tipo 'lista', então compare cada item da primeira lista com os itens da segunda lista até que seja encontrado, e se o item não for encontrado depois de passar pela segunda lista, então 'encontrado' seria = falso. o valor 'encontrado' é retornado
Caso contrário, se os objetos a serem comparados forem do tipo 'dict', compare os valores presentes para todas as respectivas chaves em ambos os objetos. (A comparação recursiva é realizada)
Ou simplesmente chame obj1 == obj2. Por padrão, funciona bem para o objeto de strings e números e para aqueles eq () é definido apropriadamente.
(Observe que o algoritmo pode ser melhorado removendo os itens encontrados no objeto2, de modo que o próximo item do objeto1 não se compare com os itens já encontrados no objeto2)
fonte
Você pode escrever sua própria função igual:
a == b
Por estar lidando com json, você terá tipos de python padrão:
dict
,list
, etc., de modo que você pode fazer difícil verificação de tipoif type(obj) == 'dict':
, etc.Exemplo aproximado (não testado):
fonte
Para outras pessoas que desejam depurar os dois objetos JSON (geralmente, há uma referência e um destino ), aqui está uma solução que você pode usar. Irá listar o " caminho " dos diferentes / incompatíveis do destino até a referência.
level
opção é usada para selecionar o quão profundo você gostaria de olhar.show_variables
opção pode ser ativada para mostrar a variável relevante.fonte