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

如何用Python或Go为元素顺序不同的嵌套JSON生成相同哈希值

实现无序嵌套JSON的一致哈希生成

要让元素顺序不同但内容等价的嵌套JSON生成相同哈希,核心是先标准化JSON结构——递归排序所有字典的键,对数组元素先标准化再排序,确保等价结构的序列化结果完全一致,最后对序列化内容计算哈希。以下是Python和Go的具体实现:


Python 实现

步骤说明

  1. 解析JSON为Python原生数据结构(dict/list)
  2. 递归标准化:
    • 对字典:按键名排序后重新构建
    • 对列表:先标准化每个元素,再对元素进行排序(通过将元素转为可哈希的元组实现)
  3. 将标准化后的结构序列化为固定格式的JSON字符串
  4. 对字符串计算哈希(示例用SHA256,可替换为MD5等)

代码示例

import json
import hashlib

def normalize(data):
    if isinstance(data, dict):
        # 排序字典的键,递归标准化每个值
        return sorted((k, normalize(v)) for k, v in data.items())
    elif isinstance(data, list):
        # 先标准化每个列表元素,再对元素排序
        normalized_elements = [normalize(item) for item in data]
        # 嵌套结构转为元组才能排序
        return sorted(tuple(item) if isinstance(item, list) else item for item in normalized_elements)
    else:
        # 基本类型直接返回
        return data

def get_consistent_hash(json_str):
    # 解析JSON
    data = json.loads(json_str)
    # 标准化结构
    normalized_data = normalize(data)
    # 序列化为JSON字符串,确保格式一致
    serialized = json.dumps(normalized_data, sort_keys=True)
    # 计算SHA256哈希
    return hashlib.sha256(serialized.encode('utf-8')).hexdigest()

# 测试示例
json1 = '''{
   "X":{
      "Y":[
         {
            "A":"1",
            "B":{
               "b1":"2",
               "b2":"2"
            }
         },
         {
            "C":"4",
            "D":{
               "d1":"5",
               "d2":"6"
            }
         }
      ],
      "Z":[
         {
            "E":{
               "e1":"7",
               "e2":"8"
            },
            "F":"9"
         }
      ]
   }
}'''

json2 = '''{
   "X":{
      "Y":[
         {
            "C":"4",
            "D":{
               "d1":"5",
               "d2":"6"
            }
         },
         {
            "A":"1",
            "B":{
               "b1":"2",
               "b2":"2"
            }
         }
      ],
      "Z":[
         {
            "E":{
               "e1":"7",
               "e2":"8"
            },
            "F":"9"
         }
      ]
   }
}'''

print(get_consistent_hash(json1))
print(get_consistent_hash(json2))
# 输出两个完全相同的哈希值

Go 实现

步骤说明

  1. 解析JSON为interface{}类型
  2. 递归标准化:
    • 对map[string]interface{}:按键名排序后重新构建map
    • 对[]interface{}:先标准化每个元素,再通过自定义排序规则对slice排序(将元素转为JSON字符串后比较)
  3. 将标准化后的结构序列化为JSON字节数组(Go的json.Marshal默认会对map键排序)
  4. 对字节数组计算哈希

代码示例

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"sort"
	"strings"
)

func normalize(data interface{}) interface{} {
	switch v := data.(type) {
	case map[string]interface{}:
		// 提取并排序map的键
		keys := make([]string, 0, len(v))
		for k := range v {
			keys = append(keys, k)
		}
		sort.Strings(keys)
		// 按排序后的键重新构建map,递归标准化每个值
		sortedMap := make(map[string]interface{})
		for _, k := range keys {
			sortedMap[k] = normalize(v[k])
		}
		return sortedMap
	case []interface{}:
		// 先标准化每个列表元素
		normalizedElements := make([]interface{}, len(v))
		for i, item := range v {
			normalizedElements[i] = normalize(item)
		}
		// 自定义排序:将元素转为JSON字符串后比较
		sort.Slice(normalizedElements, func(i, j int) bool {
			iBytes, _ := json.Marshal(normalizedElements[i])
			jBytes, _ := json.Marshal(normalizedElements[j])
			return strings.Compare(string(iBytes), string(jBytes)) < 0
		})
		return normalizedElements
	default:
		// 基本类型直接返回
		return v
	}
}

func getConsistentHash(jsonStr string) (string, error) {
	var data interface{}
	// 解析JSON
	if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
		return "", err
	}
	// 标准化结构
	normalizedData := normalize(data)
	// 序列化为JSON字节数组
	serialized, err := json.Marshal(normalizedData)
	if err != nil {
		return "", err
	}
	// 计算SHA256哈希
	hash := sha256.Sum256(serialized)
	return hex.EncodeToString(hash[:]), nil
}

func main() {
	json1 := `{
	   "X":{
	      "Y":[
	         {
	            "A":"1",
	            "B":{
	               "b1":"2",
	               "b2":"2"
	            }
	         },
	         {
	            "C":"4",
	            "D":{
	               "d1":"5",
	               "d2":"6"
	            }
	         }
	      ],
	      "Z":[
	         {
	            "E":{
	               "e1":"7",
	               "e2":"8"
	            },
	            "F":"9"
	         }
	      ]
	   }
	}`

	json2 := `{
	   "X":{
	      "Y":[
	         {
	            "C":"4",
	            "D":{
	               "d1":"5",
	               "d2":"6"
	            }
	         },
	         {
	            "A":"1",
	            "B":{
	               "b1":"2",
	               "b2":"2"
	            }
	         }
	      ],
	      "Z":[
	         {
	            "E":{
	               "e1":"7",
	               "e2":"8"
	            },
	            "F":"9"
	         }
	      ]
	   }
	}`

	hash1, err := getConsistentHash(json1)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	hash2, err := getConsistentHash(json2)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Println(hash1)
	fmt.Println(hash2)
	// 输出两个完全相同的哈希值
}

内容的提问来源于stack exchange,提问作者Sahil Sangani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:54:32