Comparez deux objets JSON avec Jackson

1. Vue d'ensemble

Dans cet article, nous examinerons la comparaison de deux objets JSON à l'aide de Jackson - une bibliothèque de traitement JSON pour Java.

2. Dépendance de Maven

Tout d'abord, ajoutons la dépendance jackson-databind Maven:

 com.fasterxml.jackson.core jackson-databind 2.11.1  

3. Utilisation de Jackson pour comparer deux objets JSON

Nous utiliserons la classe ObjectMapper pour lire un objet en tant que JsonNode.

Créons un ObjectMapper :

ObjectMapper mapper = new ObjectMapper();

3.1. Comparer deux objets JSON simples

Commençons par utiliser la méthode JsonNode.equals . La méthode equals () effectue une comparaison complète (approfondie).

Supposons que nous ayons une chaîne JSON définie comme variable s1 :

{ "employee": { "id": "1212", "fullName": "John Miles", "age": 34 } }

Et nous voulons le comparer avec un autre JSON, s2 :

{ "employee": { "id": "1212", "age": 34, "fullName": "John Miles" } }

Lisons l'entrée JSON en tant que JsonNode et comparons:

assertEquals(mapper.readTree(s1), mapper.readTree(s2));

Il est important de noter que même si l'ordre des attributs dans les variables JSON d'entrée s1 et s2 n'est pas le même, la méthode equals () ignore l'ordre et les traite comme égaux.

3.2. Comparer deux objets JSON avec un élément imbriqué

Ensuite, nous verrons comment comparer deux objets JSON ayant des éléments imbriqués.

Commençons par un JSON défini comme la variable s1 :

{ "employee": { "id": "1212", "fullName":"John Miles", "age": 34, "contact": { "email": "[email protected]", "phone": "9999999999" } } }

Comme nous pouvons le voir, le JSON contient un contact d' élément imbriqué . Nous voulons le comparer avec un autre JSON défini par s2 :

{ "employee": { "id": "1212", "age": 34, "fullName": "John Miles", "contact": { "email": "[email protected]", "phone": "9999999999" } } }

Lisons l'entrée JSON en tant que JsonNode et comparons:

assertEquals(mapper.readTree(s1), mapper.readTree(s2)); 

Encore une fois, nous devons remarquer que equals () peut également comparer deux objets JSON d'entrée avec des éléments imbriqués.

3.3. Comparer deux objets JSON contenant un élément de liste

De même, nous pouvons également comparer deux objets JSON qui contiennent un élément de liste.

Considérons ce JSON défini comme s1 :

{ "employee": { "id": "1212", "fullName": "John Miles", "age": 34, "skills": ["Java", "C++", "Python"] } }

Nous le comparons avec un autre JSON s2 :

{ "employee": { "id": "1212", "age": 34, "fullName": "John Miles", "skills": ["Java", "C++", "Python"] } }

Lisons l'entrée JSON en tant que JsonNode et comparons:

assertEquals(mapper.readTree(s1), mapper.readTree(s2));

Il est important de savoir que deux éléments de liste ne sont comparés comme égaux que s'ils ont les mêmes valeurs dans le même ordre exact.

4. Comparez deux objets JSON avec un comparateur personnalisé

JsonNode.equals fonctionne assez bien dans la plupart des cas. Jackson fournit également JsonNode.equals (comparateur, JsonNode) pour configurer un objet omparateur Java C personnalisé . Comprenons comment utiliser un comparateur personnalisé .

4.1. Comparateur personnalisé pour comparer les valeurs numériques

Comprenons comment utiliser un comparateur personnalisé pour comparer deux éléments JSON ayant des valeurs numériques.

Nous utiliserons ce JSON comme entrée s1 :

{ "name": "John", "score": 5.0 }

Comparons avec un autre JSON défini comme s2 :

{ "name": "John", "score": 5 }

Nous devons observer que les valeurs du score d' attribut dans les entrées s1 et s2 ne sont pas les mêmes.

Lisons l'entrée JSON en tant que JsonNode et comparons:

JsonNode actualObj1 = mapper.readTree(s1); JsonNode actualObj2 = mapper.readTree(s2); assertNotEquals(actualObj1, actualObj2);

Comme nous pouvons le constater, les deux objets ne sont pas égaux. La méthode standard equals () considère les valeurs 5,0 et 5 comme différentes.

Cependant, nous pouvons utiliser un comparateur personnalisé pour comparer les valeurs 5 et 5.0 et les traiter comme égales .

Créons d'abord un comparateur pour comparer deux objets NumericNode :

public class NumericNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1.equals(o2)){ return 0; } if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)){ Double d1 = ((NumericNode) o1).asDouble(); Double d2 = ((NumericNode) o2).asDouble(); if (d1.compareTo(d2) == 0) { return 0; } } return 1; } }

Ensuite, voyons comment utiliser ce comparateur :

NumericNodeComparator cmp = new NumericNodeComparator(); assertTrue(actualObj1.equals(cmp, actualObj2));

4.2. Comparateur personnalisé pour comparer les valeurs de texte

Voyons un autre exemple de comparateur personnalisé pour une comparaison insensible à la casse de deux valeurs JSON.

We'll use this JSON as input s1:

{ "name": "john", "score": 5 }

Let's compare with another JSON defined as s2:

{ "name": "JOHN", "score": 5 }

As we can see the attribute name is lowercase in input s1 and uppercase in s2.

Let's first create a Comparator to compare two TextNode objects:

public class TextNodeComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { if (o1.equals(o2)) { return 0; } if ((o1 instanceof TextNode) && (o2 instanceof TextNode)) { String s1 = ((TextNode) o1).asText(); String s2 = ((TextNode) o2).asText(); if (s1.equalsIgnoreCase(s2)) { return 0; } } return 1; } }

Let's see how to compare s1 and s2 using TextNodeComparator:

JsonNode actualObj1 = mapper.readTree(s1); JsonNode actualObj2 = mapper.readTree(s2); TextNodeComparator cmp = new TextNodeComparator(); assertNotEquals(actualObj1, actualObj2); assertTrue(actualObj1.equals(cmp, actualObj2));

Finally, we can see using a custom comparator object while comparing two JSON objects can be very useful when the input JSON element value is not exactly the same but we still want to treat them as equal.

5. Conclusion

Dans ce tutoriel rapide, nous avons vu comment utiliser Jackson pour comparer deux objets JSON et utiliser un comparateur personnalisé .

Bien sûr, comme toujours, le code source complet de tous les exemples discutés ici peut être trouvé sur GitHub.