Comparez deux objets JSON avec Gson

1. Vue d'ensemble

JSON est une représentation sous forme de chaîne de données. Nous pouvons souhaiter comparer ces données dans nos algorithmes ou tests. Et bien qu'il soit possible de comparer des chaînes contenant JSON, la comparaison de chaînes est sensible aux différences de représentation , plutôt que de contenu.

Pour surmonter cela et comparer sémantiquement les données JSON, nous devons charger les données dans une structure en mémoire qui n'est pas affectée par des éléments tels que les espaces ou par l'ordre des clés d'un objet.

Dans ce court didacticiel, nous allons résoudre ce problème à l'aide de Gson, une bibliothèque de sérialisation \ désérialisation JSON qui peut effectuer une comparaison approfondie entre les objets JSON.

2. JSON sémantiquement identique dans différentes chaînes

Examinons de plus près le problème que nous essayons de résoudre.

Supposons que nous ayons deux chaînes, représentant les mêmes données JSON, mais l'une d'elles a des espaces supplémentaires à la fin:

String string1 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27 }"; String string2 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27}";

Bien que le contenu des objets JSON soit égal, la comparaison de ce qui précède en tant que chaînes montrera une différence:

assertNotEquals(string1, string2);

La même chose se produirait si l'ordre des clés dans un objet était modifié, même si JSON n'est généralement pas sensible à cela:

String string1 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27}"; String string2 = "{\"age\": 27, \"fullName\": \"Emily Jenkins\"}"; assertNotEquals(string1, string2);

C'est pourquoi nous aurions intérêt à utiliser une bibliothèque de traitement JSON pour comparer les données JSON.

3. Dépendance de Maven

Pour utiliser Gson, ajoutons d'abord la dépendance Gson Maven:

 com.google.code.gson gson 2.8.6 

4. Analyse JSON en objets Gson

Avant de nous plonger dans la comparaison d'objets, examinons comment Gson représente les données JSON en Java.

Lorsque vous travaillez avec JSON en Java, nous devons d'abord convertir la chaîne JSON en un objet Java. Gson fournit JsonParser qui analyse le JSON source dans une arborescence JsonElement :

JsonParser parser = new JsonParser(); String objectString = "{\"customer\": {\"fullName\": \"Emily Jenkins\", \"age\": 27 }}"; String arrayString = "[10, 20, 30]"; JsonElement json1 = parser.parse(objectString); JsonElement json2 = parser.parse(arrayString);

JsonElement est une classe abstraite, représentant un élément de JSON. La méthode parse retourne une implémentation de JsonElement ; soit un JsonObject, JsonArray, JsonPrimitive ou JsonNull:

assertTrue(json1.isJsonObject()); assertTrue(json2.isJsonArray());

Chacune de ces sous-classes ( JsonObject, JsonArray, etc.) remplace la méthode Object.equals , fournissant une comparaison JSON approfondie efficace.

5. Cas d'utilisation de comparaison de Gson

5.1. Comparer deux objets JSON simples

Supposons que nous ayons deux chaînes, représentant des objets JSON simples, où l'ordre des clés est différent:

Le premier objet a fullName antérieur à age :

{ "customer": { "id": 44521, "fullName": "Emily Jenkins", "age": 27 } }

La seconde inverse l'ordre:

{ "customer": { "id": 44521, "age": 27, "fullName": "Emily Jenkins" } }

Nous pouvons simplement les analyser et les comparer:

assertEquals(parser.parse(string1), parser.parse(string2));

Dans ce cas, le JsonParser renvoie un JsonObject , dont l' implémentation égale n'est pas sensible à l'ordre .

5.2. Comparer deux tableaux JSON

Dans le cas de tableaux JSON, JsonParser renverra un JsonArray.

Si nous avons un tableau dans un ordre:

[10, 20, 30]
assertTrue(parser.parse(string1).isJsonArray());

On peut le comparer à un autre dans un ordre différent:

[20, 10, 30]

Contrairement à JsonObject , la méthode equals de JsonArray est sensible à l'ordre , donc ces tableaux ne sont pas égaux, ce qui est sémantiquement correct:

assertNotEquals(parser.parse(string1), parser.parse(string2));

5.3. Comparer deux objets JSON imbriqués

Comme nous l'avons vu précédemment, JsonParser peut analyser la structure arborescente de JSON. Chaque JsonObject et JsonArray contiennent d'autres objets JsonElement , qui peuvent eux-mêmes être de type JsonObject ou JsonArray .

Lorsque nous utilisons equals , il compare tous les membres de manière récursive, ce qui signifie que les objets imbriqués sont également comparables:

S'il s'agit de string1 :

{ "customer": { "id": "44521", "fullName": "Emily Jenkins", "age": 27, "consumption_info": { "fav_product": "Coke", "last_buy": "2012-04-23" } } }

Et ce JSON est string2 :

{ "customer": { "fullName": "Emily Jenkins", "id": "44521", "age": 27, "consumption_info": { "last_buy": "2012-04-23", "fav_product": "Coke" } } }

Ensuite, nous pouvons toujours utiliser la méthode equals pour les comparer:

assertEquals(parser.parse(string1), parser.parse(string2));

6. Conclusion

Dans ce court article, nous avons examiné les défis de la comparaison de JSON en tant que chaîne . Nous avons vu comment Gson nous permet d'analyser ces chaînes dans une structure d'objet qui prend en charge la comparaison.

Comme toujours, le code source des exemples ci-dessus se trouve à l'adresse over sur GitHub.