概述
在本文中,我们将使用 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> {@Overridepublic 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> {@Overridepublic 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 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
