如何按值排序JSON以忽略顺序实现准确的DIFF对比
问题原因
你之前配置的SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS和MapperFeature.SORT_PROPERTIES_ALPHABETICALLY仅作用于JSON对象的键值对排序,不会处理JSON数组内部的元素顺序,你遇到的差异本质是additional_data_value_list数组内的元素顺序不同,因此这两个配置无法解决问题。
解决方案
需要先手动递归遍历JSON节点,对所有additional_data_value_list数组的元素按照additional_data_item_code的字母顺序排序,再执行序列化对比,完整修改后代码如下:
import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.ObjectNode import javax.json.Json import javax.json.JsonPatch import java.io.StringReader String template = """ {"preparation_order_list" : [ { "net_weight_to_prepare" : 12.33, "additional_data_value_list" : [ { "additional_data_item_code" : "NB_SUP_HET", "additional_data_item_value" : "001821" }, { "additional_data_item_code" : "NB_SUP_SOL", "additional_data_item_value" : "002000" }, { "additional_data_item_code" : "WEI_MAX", "additional_data_item_value" : "000007358" } ] }]} """ String file_to_compare = """ {"preparation_order_list" : [ { "net_weight_to_prepare" : 12.33, "additional_data_value_list" : [ { "additional_data_item_code" : "WEI_MAX", "additional_data_item_value" : "000007358" }, { "additional_data_item_code" : "NB_SUP_SOL", "additional_data_item_value" : "002000" }, { "additional_data_item_code" : "NB_SUP_HET", "additional_data_item_value" : "001821" } ] }]} """ // 自定义排序方法:遍历所有节点,对additional_data_value_list数组按code排序 def sortAdditionalDataList(JsonNode node) { if (node.isObject()) { def fields = node.fields() while (fields.hasNext()) { def entry = fields.next() if (entry.key == "additional_data_value_list" && entry.value.isArray()) { ArrayNode arrayNode = (ArrayNode) entry.value // 按additional_data_item_code字母排序,如需自定义优先级可修改此处规则 def sortedList = arrayNode.elements().toList().sort { it.get("additional_data_item_code").asText() } // 清空原数组,重新插入排序后的元素 arrayNode.removeAll() sortedList.each { arrayNode.add(it) } } else { // 递归遍历子节点 sortAdditionalDataList(entry.value) } } } else if (node.isArray()) { // 递归遍历数组内的每个元素 node.elements().each { sortAdditionalDataList(it) } } return node } ObjectMapper mapper = new ObjectMapper() // 保留原有对象键排序配置 mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) // 读取两个JSON并执行自定义排序 JsonNode templateNode = sortAdditionalDataList(mapper.readTree(template)) JsonNode compareNode = sortAdditionalDataList(mapper.readTree(file_to_compare)) // 序列化后对比 String prettyTemplateJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(templateNode) String prettyApiJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(compareNode) // 执行diff,此时输出为[]无差异 def jsonStructInput = Json.createReader(new StringReader(prettyApiJson)).read() def jsonStructTemplate = Json.createReader(new StringReader(prettyTemplateJson)).read() JsonPatch diff = Json.createDiff(jsonStructTemplate, jsonStructInput) println diff.toString()
如果需要固定自定义排序优先级,可替换排序逻辑为:
// 自定义顺序:NB_SUP_HET排第一,NB_SUP_SOL排第二,WEI_MAX排第三 def sortOrder = ["NB_SUP_HET", "NB_SUP_SOL", "WEI_MAX"] def sortedList = arrayNode.elements().toList().sort { sortOrder.indexOf(it.get("additional_data_item_code").asText()) }
内容的提问来源于stack exchange,提问作者Sebastien TANIERE
相关产品推荐
相关产品推荐

