Probando la igualdad de dos objetos JSON ignorando el orden de los hijos en Java [cerrado]

Resuelto Jeff asked hace 14 años • 28 respuestas

Estoy buscando una biblioteca de análisis JSON que admita la comparación de dos objetos JSON ignorando el orden de los hijos, específicamente para pruebas unitarias de JSON que regresan de un servicio web.

¿Alguna de las principales bibliotecas JSON admite esto? La biblioteca org.json simplemente hace una comparación de referencias.

Jeff avatar Feb 13 '10 00:02 Jeff
Aceptado

Pruebe JSONAssert de Skyscreamer .

Su modo no estricto tiene dos grandes ventajas que lo hacen menos frágil:

  • Extensibilidad del objeto (por ejemplo, con un valor esperado de {id:1} , esto aún pasaría: {id:1,moredata:'x'} ).
  • Orden de matriz suelta (por ejemplo, ['perro','gato']==['gato','perro'])

En modo estricto, se comporta más como la clase de prueba de json-lib.

Una prueba se parece a esto:

@Test
public void testGetFriends() {
    JSONObject data = getRESTData("/friends/367.json");
    String expected = "{friends:[{id:123,name:\"Corby Page\"}"
        + ",{id:456,name:\"Solomon Duskis\"}]}";
    JSONAssert.assertEquals(expected, data, false);
}

Los parámetros en la llamada JSONAssert.assertEquals() son expectJSONString , actualDataString e isStrict .

Los mensajes de resultados son bastante claros, lo cual es importante cuando se comparan objetos JSON realmente grandes.

Carter Page avatar Apr 06 '2012 17:04 Carter Page

Como punto arquitectónico general, normalmente desaconsejo dejar que las dependencias de un formato de serialización particular se extiendan más allá de su capa de almacenamiento/red; por lo tanto, primero recomendaría que considere probar la igualdad entre los objetos de su propia aplicación en lugar de sus manifestaciones JSON.

Dicho esto, actualmente soy un gran admirador de Jackson y mi lectura rápida de su implementación de ObjectNode.equals() sugiere que hace la comparación de membresía establecida que desea:

public boolean equals(Object o)
{
    if (o == this) return true;
    if (o == null) return false;
    if (o.getClass() != getClass()) {
        return false;
    }
    ObjectNode other = (ObjectNode) o;
    if (other.size() != size()) {
        return false;
    }
    if (_children != null) {
        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
            String key = en.getKey();
            JsonNode value = en.getValue();

            JsonNode otherValue = other.get(key);

            if (otherValue == null || !otherValue.equals(value)) {
                return false;
            }
        }
    }
    return true;
}
Jolly Roger avatar Feb 13 '2010 00:02 Jolly Roger

Usando GSON

JsonParser parser = new JsonParser();
JsonElement o1 = parser.parse("{a : {a : 2}, b : 2}");
JsonElement o2 = parser.parse("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);

Editar: desde GSON v2.8.6, el método de instancia JsonParser.parseestá en desuso. Tienes que usar el método estático JsonParser.parseString:

JsonElement o1 = JsonParser.parseString("{a : {a : 2}, b : 2}");
JsonElement o2 = JsonParser.parseString("{b : 2, a : {a : 2}}");
assertEquals(o1, o2);
axelhzf avatar Jan 30 '2012 14:01 axelhzf

Yo haría lo siguiente,

JSONObject obj1 = /*json*/;
JSONObject obj2 = /*json*/;

ObjectMapper mapper = new ObjectMapper();

JsonNode tree1 = mapper.readTree(obj1.toString());
JsonNode tree2 = mapper.readTree(obj2.toString());

return tree1.equals(tree2);
josh avatar Jun 11 '2014 00:06 josh