Java Jackson如何实现忽略键与数组元素顺序的JSON对比
基于Jackson实现满足需求的JSON对比功能
核心思路
通过Jackson将两个JSON字符串解析为JsonNode树结构,递归遍历节点做对比,针对不同节点类型做特殊处理:
- 忽略对象节点的键排序差异,同时严格校验键集合完全一致,任意一方存在多余字段直接判定不相等
- 忽略数组节点的元素排序差异,同时保证元素的种类和数量完全匹配
- 基础值类型直接做等值对比
前置依赖
确保项目已经引入Jackson核心模块,常规SpringBoot项目默认已集成,手动引入的Maven配置如下:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>根据你的项目版本选择即可</version> </dependency>
完整实现代码
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ArrayNode; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ValueNode; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class JsonCompareUtils { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public static boolean compareJson(String json1, String json2) throws JsonProcessingException { JsonNode node1 = OBJECT_MAPPER.readTree(json1); JsonNode node2 = OBJECT_MAPPER.readTree(json2); return compareJsonNode(node1, node2); } private static boolean compareJsonNode(JsonNode node1, JsonNode node2) { // 节点类型不同直接不相等 if (node1.getNodeType() != node2.getNodeType()) { return false; } // 处理值类型节点(字符串、数字、布尔、null等) if (node1 instanceof ValueNode) { return node1.equals(node2); } // 处理对象类型节点 if (node1 instanceof ObjectNode obj1 && node2 instanceof ObjectNode obj2) { // 先判断字段数量是否一致,不一致说明有多余字段 if (obj1.size() != obj2.size()) { return false; } // 遍历所有字段逐一对比 Iterator<String> fieldNames = obj1.fieldNames(); while (fieldNames.hasNext()) { String fieldName = fieldNames.next(); if (!obj2.has(fieldName)) { return false; } if (!compareJsonNode(obj1.get(fieldName), obj2.get(fieldName))) { return false; } } return true; } // 处理数组类型节点 if (node1 instanceof ArrayNode arr1 && node2 instanceof ArrayNode arr2) { // 数组长度不同直接不相等 if (arr1.size() != arr2.size()) { return false; } // 把第二个数组的元素转成列表,方便匹配后移除避免重复匹配 List<JsonNode> arr2Elements = new ArrayList<>(); arr2.forEach(arr2Elements::add); // 遍历第一个数组的每个元素,在第二个数组中找匹配项 for (JsonNode elem1 : arr1) { boolean matched = false; Iterator<JsonNode> it = arr2Elements.iterator(); while (it.hasNext()) { JsonNode elem2 = it.next(); if (compareJsonNode(elem1, elem2)) { it.remove(); matched = true; break; } } if (!matched) { return false; } } // 所有元素都匹配完成 return arr2Elements.isEmpty(); } // 其他未知类型节点默认不相等 return false; } }
效果验证
可以通过以下场景测试是否符合需求:
- 测试场景1:对象键顺序不同、数组元素顺序不同,内容完全一致:返回
true - 测试场景2:其中一个JSON多了任意字段:返回
false - 测试场景3:数组元素数量不一致:返回
false - 测试场景4:数组元素数量一致但内容存在差异:返回
false
内容的提问来源于stack exchange,提问作者hello2244
相关产品推荐
相关产品推荐

