Compare Two JSON Objects with Jackson – 用Jackson比较两个JSON对象

最后修改: 2019年 7月 10日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll have a look at comparing two JSON objects using Jackson — a JSON processing library for Java.

在本教程中,我们将使用Jackson–一个用于Java的JSON处理库,来看看如何比较两个JSON对象。

2. Maven Dependency

2.Maven的依赖性

First, let’s add the jackson-databind Maven dependency:

首先,我们来添加 jackson-databindMaven依赖。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

3. Using Jackson to Compare Two JSON Objects

3.使用Jackson来比较两个JSON对象

We’ll be using the ObjectMapper class to read an object as a JsonNode.

我们将使用ObjectMapper类来读取一个对象作为JsonNode

Let’s create an ObjectMapper:

让我们创建一个ObjectMapper

ObjectMapper mapper = new ObjectMapper();

3.1. Compare Two Simple JSON Objects

3.1.比较两个简单的JSON对象

Let’s begin by using the JsonNode.equals method. The equals() method performs a full (deep) comparison.

让我们首先使用JsonNode.equals方法。equals()方法执行全面(深度)比较。

Suppose we have a JSON string defined as the s1 variable:

假设我们有一个JSON字符串定义为s1变量。

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

And we want to compare it with another JSON, s2:

而我们想把它与另一个JSON,s2进行比较。

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

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

让我们把输入的JSON读成JsonNode并进行比较。

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

It’s important to note that even though the order of attributes in input JSON variables s1 and s2 is not the same, the equals() method ignores the order and treats them as equal.

需要注意的是,即使输入的JSON变量s1s2中的属性顺序不一样,equals()方法忽略了顺序,将它们视为相等。

3.2. Compare Two JSON Objects With a Nested Element

3.2.用一个嵌套元素比较两个JSON对象

Next, we’ll see how to compare two JSON objects having nested elements.

接下来,我们将看到如何比较两个有嵌套元素的JSON对象。

Let’s begin with a JSON defined as the s1 variable:

让我们从一个定义为s1变量的JSON开始。

{ 
    "employee":
    {
        "id": "1212",
        "fullName":"John Miles",
        "age": 34,
        "contact":
        {
            "email": "john@xyz.com",
            "phone": "9999999999"
        }
    }
}

As we can see, the JSON contains a nested element contact.

我们可以看到,JSON包含一个嵌套元素contact

We want to compare it with another JSON defined by s2:

我们想把它与另一个由s2定义的JSON进行比较。

{
    "employee":
    {
        "id": "1212",
        "age": 34,
        "fullName": "John Miles",
        "contact":
        {
            "email": "john@xyz.com",
            "phone": "9999999999"
        }
    }
}

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

让我们把输入的JSON读成JsonNode并进行比较。

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

Again, we should notice that equals() can also compare two input JSON objects with nested elements.

同样,我们应该注意到,equals()也可以比较两个带有嵌套元素的输入JSON对象。

3.3. Compare Two JSON Objects Containing a List Element

3.3.比较两个包含一个列表元素的JSON对象

Similarly, we can also compare two JSON objects that contain a list element.

同样地,我们也可以比较两个包含列表元素的JSON对象。

Let’s consider this JSON defined as s1:

让我们考虑这个定义为s1的JSON。

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

We are comparing it with another JSON, s2:

我们正在将其与另一个JSON,s2进行比较。

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

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

让我们把输入的JSON读成JsonNode并进行比较。

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

It’s important to know that two list elements are only compared as equal if they have the same values in the exact same order.

重要的是要知道,两个列表元素只有在它们的值完全相同的情况下才会被比较为相等。

4. Compare Two JSON Objects With a Custom Comparator

4.用一个自定义比较器比较两个JSON对象

JsonNode.equals works quite well in most cases. Jackson also provides JsonNode.equals(comparator, JsonNode) to configure a custom Java Comparator object.

JsonNode.equals在大多数情况下效果很好。Jackson还提供了JsonNode.equals(comparator, JsonNode)来配置一个自定义的JavaComparator对象。

Let’s understand how to use a custom Comparator.

让我们了解如何使用自定义比较器

4.1. Custom Comparator to Compare Numeric Values

4.1.自定义比较器来比较数字值

Let’s look at how to use a custom Comparator to compare two JSON elements having numeric values.

让我们看看如何使用一个自定义的比较器来比较两个具有数字值的JSON元素。

We’ll use this JSON as input s1:

我们将使用这个JSON作为输入s1

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

Let’s compare with another JSON defined as s2:

让我们与另一个定义为s2的JSON进行比较。

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

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

我们需要观察到,输入s1s2中的属性score的值是不一样的。

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

让我们把输入的JSON读成JsonNode并进行比较。

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

assertNotEquals(actualObj1, actualObj2);

Notice that the two objects are not equal. The standard equals() method considers values 5.0 and 5 as different.

请注意,这两个对象是不相等的。标准的equals() 方法认为值5.0和5是不同的。

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

然而,我们可以使用一个自定义的比较器来比较数值5和5.0,并将其视为相等。

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

让我们首先创建一个Comparator来比较两个NumericNode对象。

public class NumericNodeComparator implements Comparator<JsonNode> 
{
    @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

4.2.自定义比较器来比较文本值

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

让我们看看另一个自定义Comparator的例子,对两个JSON值进行不区分大小写的比较

We’ll use this JSON as input s1:

我们将使用这个JSON作为输入s1

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

Let’s compare with another JSON defined as s2:

让我们与另一个定义为s2的JSON进行比较。

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

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

我们可以看到,属性name在输入s1中是小写,在s2中是大写。

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

让我们首先创建一个Comparator来比较两个TextNode对象。

public class TextNodeComparator implements Comparator<JsonNode> 
{
    @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:

让我们看看如何使用s1s2来比较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.

最后,我们可以看到在比较两个JSON对象时使用一个自定义的比较器对象当输入的JSON元素值不完全相同,但我们仍然希望将其视为相等时,可以非常有用。

5. Conclusion

5.总结

In this quick article, we’ve seen how to use Jackson to compare two JSON objects and use a custom comparator

在这篇快速文章中,我们已经看到如何使用Jackson来比较两个JSON对象,并使用一个自定义的比较器

As always, the full source code of all the examples discussed here can be found over on GitHub.

一如既往,这里讨论的所有示例的完整源代码都可以在GitHub上找到over