280 votes

Comparer deux objets JSON en Java

Je suis à la recherche d'une bibliothèque d'analyse syntaxique JSON qui permette de comparer deux objets JSON en ignorant l'ordre des enfants, notamment pour effectuer des tests unitaires sur le JSON renvoyé par un service Web par rapport à une valeur attendue.

L'une des principales bibliothèques JSON prend-elle en charge cette fonction ? org.json effectue simplement une comparaison de référence.

188voto

Carter Page Points 905

Essayez celui de Skyscreamer JSONAssert .

Son non stricte présente deux avantages majeurs qui le rendent moins cassant :

  • Extensibilité des objets (par exemple avec une valeur attendue de {id:1} cela passerait quand même : {id:1,moredata:'x'} .)
  • Ordre libre des tableaux (par exemple, ['chien', 'chat']==['chat', 'chien'])

En mode strict, elle se comporte plus comme la classe de test de json-lib.

Un test ressemble à quelque chose comme ça :

@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);
}

Les paramètres de l'appel JSONAssert.assertEquals() sont les suivants attenduJSONString , actualDataString et isStrict .

Les messages de résultat sont assez clairs, ce qui est important lorsque l'on compare des objets JSON très volumineux.

99voto

Jolly Roger Points 512

D'un point de vue architectural, je déconseille généralement de laisser les dépendances à l'égard d'un format de sérialisation particulier s'étendre au-delà de votre couche de stockage/réseau. Ainsi, je vous recommande d'abord d'envisager de tester l'égalité entre vos propres objets d'application plutôt que leurs manifestations JSON.

Ceci dit, je suis actuellement un grand fan de Jackson qui, d'après ma lecture rapide de leur implémentation ObjectNode.equals(), effectue la comparaison d'appartenance à un ensemble que vous souhaitez :

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;
}

57voto

axelhzf Points 148

Utilisation du 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);

20voto

hertzsprung Points 1529

Vous pouvez essayer d'utiliser la fonction JSONAssert classe :

JSONAssert.assertEquals(
  "{foo: 'bar', baz: 'qux'}",
  JSONObject.fromObject("{foo: 'bar', baz: 'xyzzy'}"));

Donne :

junit.framework.ComparisonFailure: objects differed at key [baz]; expected:<[qux]> but was:<[xyzzy]>

14voto

kevinarpe Points 2902

Si vous utilisez déjà JUnit, la dernière version utilise désormais Hamcrest. Il s'agit d'un cadre de correspondance générique (particulièrement utile pour les tests unitaires) qui peut être étendu pour construire de nouvelles correspondances.

Il existe une petite bibliothèque open source appelée hamcrest-json avec des correspondances tenant compte de JSON. Il est bien documenté, testé et soutenu. Vous trouverez ci-dessous quelques liens utiles :

Exemple de code utilisant des objets de la bibliothèque JSON org.json.simple :

Assert.assertThat(
    jsonObject1.toJSONString(),
    SameJSONAs.sameJSONAs(jsonObject2.toJSONString()));

En option, vous pouvez (1) autoriser les tableaux "d'ordre quelconque" et (2) ignorer les champs supplémentaires.

Comme il existe une variété de bibliothèques JSON pour Java ( Jackson , GSON , json-lib etc.), il est utile que hamcrest-json supporte le texte JSON (comme java.lang.String ), ainsi que le support natif des objets de la bibliothèque JSON de Douglas Crockford. org.json .

Enfin, si vous n'utilisez pas JUnit, vous pouvez utiliser Hamcrest directement pour les assertions. ( J'ai écrit à ce sujet ici. )

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X