概述
在本文中,我们将使用 Jackson(Java 的 JSON 处理库),比较两个 JSON 对象。
Maven 依赖
首先,让我们添加 jackson-databind Maven 依赖项:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
使用 Jackson 比较两个 JSON 对象
我们将使用 ObjectMapper 类将 JSON 字符串转成 JsonNode,然后使用 JsonNode 的 equals 方法。
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(jsonStr);
JsonNode.equals
方法支持执行完整(深度)比较。
比较两个简单的 JSON 对象
假设我们有一个定义为 s1 变量的 JSON 字符串:
{
"employee": {
"id": "1212",
"fullName": "John Miles",
"age": 34
}
}
我们将其与另一个 JSON s2 进行比较:
{
"employee": {
"id": "1212",
"age": 34,
"fullName": "John Miles"
}
}
将输入的 JSON 读取为 JsonNode 并进行比较:
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(jsonNode2));
需要注意的是即使输入的 JSON 变量 s1 和 s2 中的属性顺序不相同,equals()
方法也会忽略顺序并将它们视为相等。
比较带有嵌套元素的两个 JSON 对象
假设我们有一个定义为 s1 变量的 JSON 字符串:
{
"employee": {
"id": "1212",
"fullName": "John Miles",
"age": 34,
"contact": {
"email": "john@xyz.com",
"phone": "9999999999"
}
}
}
如我们所见,JSON 包含一个嵌套元素联系人。我们将其与另一个 JSON s2 进行比较:
{
"employee": {
"id": "1212",
"age": 34,
"fullName": "John Miles",
"contact": {
"email": "john@xyz.com",
"phone": "9999999999"
}
}
}
将输入的 JSON 读取为 JsonNode 并进行比较:
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(jsonNode2));
同样,我们应该注意到 equals()
方法也可以比较两个具有嵌套元素的 JSON 对象。
比较两个包含列表元素的 JSON 对象
同样,我们还可以比较两个包含 List 元素的 JSON 对象。
假设我们有一个定义为 s1 变量的 JSON 字符串:
{
"employee": {
"id": "1212",
"fullName": "John Miles",
"age": 34,
"skills": ["Java", "C++", "Python"]
}
}
我们将其与另一个 JSON s2 进行比较:
{
"employee": {
"id": "1212",
"age": 34,
"fullName": "John Miles",
"skills": ["Java", "C++", "Python"]
}
}
将输入的 JSON 读取为 JsonNode 并进行比较:
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(jsonNode2));
需要注意的是,只有当两个列表元素的值的顺序完全相同时,才会被比视为相等。
使用自定义比较器比较两个 JSON 对象
在大多数情况下,JsonNode.equals(JsonNode)
方法能够满足要求了。
Jackson 还提供了 JsonNode.equals(``Comparator``,JsonNode)
方法来配置自定义 Java Comparator 对象,用来满足一些自定义需求。
自定义比较器来比较数字值
让我们了解如何使用自定义比较器来比较两个具有数字值的 JSON 元素。
假设我们有一个定义为 s1 变量的 JSON 字符串:
{
"name": "John",
"score": 5.0
}
我们将其与另一个 JSON s2 进行比较:
{
"name": "John",
"score": 5
}
将输入的 JSON 读取为 JsonNode 并进行比较:
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(jsonNode2));
我们注意到,两个 JSON 对象不相等,标准的 equals()
方法认为 5.0 和 5 是不相同的。
但是,我们可以自定义比较器,将 5.0 和 5 视为相同的值。
首先,我们创建一个 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;
}
}
接下来,让我们看看如何使用此比较器:
NumericNodeComparator cmp = new NumericNodeComparator();
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(cmp, jsonNode2));
自定义比较器来比较文本值
让我们看一下自定义比较器的另一个示例,该示例比较两个 JSON 值时是否区分大小写。
假设我们有一个定义为 s1 变量的 JSON 字符串:
{
"name": "john",
"score": 5
}
我们将其与另一个 JSON s2 进行比较:
{
"name": "JOHN",
"score": 5
}
如我们所见,属性 name 在 s1 中为小写,在 s2 中为大写。
创建一个 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;
}
}
接下来,让我们看看如何使用此比较器:
TextNodeComparator cmp = new TextNodeComparator();
JsonNode jsonNode1 = mapper.readTree(s1);
JsonNode jsonNode2 = mapper.readTree(s2);
System.out.println(jsonNode1.equals(cmp, jsonNode2));
在输入的 JSON 元素值不完全相同但我们仍希望将它们视为相等时,在比较两个 JSON 对象时使用自定义比较器对象非常有用。
转载
https://www.baeldung.com/jackson-compare-two-json-objects
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/psygdn 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。