You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按值排序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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:09:03