Bandingkan Dua Objek JSON dengan Jackson

1. Gambaran keseluruhan

Dalam artikel ini, kita akan melihat membandingkan dua objek JSON menggunakan Jackson - perpustakaan pemprosesan JSON untuk Java.

2. Ketergantungan Maven

Pertama, mari tambah ketergantungan jackson-databaseind Maven:

 com.fasterxml.jackson.core jackson-databind 2.11.1  

3. Menggunakan Jackson untuk Membandingkan Dua Objek JSON

Kami akan menggunakan kelas ObjectMapper untuk membaca objek sebagai JsonNode.

Mari buat ObjectMapper :

ObjectMapper mapper = new ObjectMapper();

3.1. Bandingkan Dua Objek JSON Mudah

Mari kita mulakan dengan menggunakan kaedah JsonNode.equals . Kaedah sama () melakukan perbandingan penuh (dalam).

Katakan kita mempunyai rentetan JSON yang ditakrifkan sebagai pemboleh ubah s1 :

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

Dan kami mahu membandingkannya dengan JSON lain, s2 :

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

Mari baca input JSON sebagai JsonNode dan bandingkan:

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

Penting untuk diperhatikan bahawa walaupun susunan atribut dalam input JSON pemboleh ubah s1 dan s2 tidak sama, kaedah sama () mengabaikan susunan dan memperlakukannya sama.

3.2. Bandingkan Dua Objek JSON dengan Elemen Bersarang

Seterusnya, kita akan melihat bagaimana membandingkan dua objek JSON yang mempunyai unsur bersarang.

Mari kita mulakan dengan JSON yang ditakrifkan sebagai pemboleh ubah s1 :

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

Seperti yang kita lihat, JSON mengandungi kenalan elemen bersarang . Kami ingin membandingkannya dengan JSON lain yang ditentukan oleh s2 :

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

Mari baca input JSON sebagai JsonNode dan bandingkan:

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

Sekali lagi, kita harus perhatikan bahawa sama () juga dapat membandingkan dua objek JSON input dengan elemen bersarang.

3.3. Bandingkan Dua Objek JSON yang Mengandungi Elemen Senarai

Begitu juga, kita juga dapat membandingkan dua objek JSON yang mengandungi elemen senarai.

Mari kita anggap JSON ini ditakrifkan sebagai s1 :

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

Kami membandingkannya dengan JSON s2 lain :

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

Mari baca input JSON sebagai JsonNode dan bandingkan:

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

Penting untuk mengetahui bahawa dua elemen senarai hanya dibandingkan sama jika mempunyai nilai yang sama dalam urutan yang sama.

4. Bandingkan Dua Objek JSON dengan Pembanding Khusus

JsonNode.equals works quite well in most of the cases. Jackson also provides JsonNode.equals(comparator, JsonNode) to configure a custom Java Comparator object. Let's understand how to use a custom Comparator.

4.1. Custom Comparator to Compare Numeric Values

Let's understand how to use a custom Comparator to compare two JSON elements having numeric values.

We'll use this JSON as input s1:

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

Let's compare with another JSON defined as s2:

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

We need to observe that the values of attribute score in inputs s1 and s2 are not the same.

Let's read the input JSON as JsonNode and compare:

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

As we can notice, the two objects are not equal. The standard equals() method considers values 5.0 and 5 as different.

However, we can use a custom Comparator to compare values 5 and 5.0 and treat them as equal.

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

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

Next, let's see how to use this Comparator:

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

4.2. Custom Comparator to Compare Text Values

Let's see another example of a custom Comparator for a case-insensitive comparison of two JSON values.

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

Dalam tutorial ringkas ini, kami telah melihat bagaimana menggunakan Jackson untuk membandingkan dua objek JSON dan menggunakan pembanding tersuai .

Sudah tentu, seperti biasa, kod sumber lengkap dari semua contoh yang dibincangkan di sini boleh didapati di GitHub.