【Python】无序JSON的HASH值计算


由于python3取消了cmp函数,无法进行dict的排序。但有时候我们需要对JSON文件进行去重/聚合等操作,就变得并不方便了。本文介绍 json-fingerprint 无序JSON的HASH值计算,从而对JSON进行比较和排序

相关文献

安装

pip install json-fingerprint

JSON 规范化

函数在对输出进行哈希处理之前,在内部将数据转换为规范化(规范)格式。

替代规格

大多数现有的 JSON 规范化/规范化规范和相关实现在三个关键方面运行:数据结构、值和数据排序。虽然键值对(对象)的排序很简单,但问题通常来自数组的排序。

JSON 规范(包括最新的 RFC 8259)始终认为数组元素的顺序是有意义的。随着数据在各种系统中被序列化、传输、反序列化和再次序列化,在许多情况下,保持数组元素的顺序变得不切实际,甚至是不可能的。因此,这使得跨多个系统创建和比较 JSON 数据的安全哈希成为一个复杂的过程。

例子

JSON => JSON fingerprint

create()函数需要三个参数:input(有效的 JSON 字符串)、hash 函数(支持 SHA256SHA384SHA512)和 版本 (1)。

import json
import json_fingerprint
from json_fingerprint import hash_functions

if __name__ == '__main__':
    json_1 = json.dumps([3, 2, 1, [True, False], {
    
    "foo": "bar"}])
    json_2 = json.dumps([2, {
    
    "foo": "bar"}, 1, [False, True], 3])  # Different order

    fp_1 = json_fingerprint.create(input=json_1, hash_function=hash_functions.SHA256, version=1)
    fp_2 = json_fingerprint.create(input=json_2, hash_function=hash_functions.SHA256, version=1)

    print(f"Fingerprint 1: {
      
      fp_1}")
    print(f"Fingerprint 2: {
      
      fp_2}")

这将输出两个相同的Fingerprint,而不管 json 元素的顺序如何:

Fingerprint 1: jfpv1$sha256$2ecb0c919fcb06024f55380134da3bbaac3879f98adce89a8871706fe50dda03
Fingerprint 2: jfpv1$sha256$2ecb0c919fcb06024f55380134da3bbaac3879f98adce89a8871706fe50dda03

JSON fingerprint => (hash, hash_function, version)

decode()函数可以用于解码。它返回元组中的版本、哈希函数和安全哈希。

import json_fingerprint

fp = "jfpv1$sha256$2ecb0c919fcb06024f55380134da3bbaac3879f98adce89a8871706fe50dda03"

version, hash_function, hash = json_fingerprint.decode(fingerprint=fp)

print(f"JSON fingerprint version: {
      
      version}")
print(f"Hash function: {
      
      hash_function}")
print(f"Hash hex digest: {
      
      hash}")

这将输出构成指纹的各个元素,如下所示:

JSON fingerprint version: 1
Hash function: sha256
Hash hex digest: 2ecb0c919fcb06024f55380134da3bbaac3879f98adce89a8871706fe50dda03

Match fingerprints

match() True False target_fingerprint是另一个方便的函数,它将 JSON 数据与指纹进行匹配,并返回 or 取决于数据是否与指纹匹配。在内部,它将根据参数自动选择正确的版本和哈希函数。

import json
import json_fingerprint

json_1 = json.dumps([3, 2, 1, [True, False], {
    
    "foo": "bar"}])
json_2 = json.dumps([3, 2, 1])

# "target_fp" contains the JSON fingerprint of "json_1"
target_fp = "jfpv1$sha256$2ecb0c919fcb06024f55380134da3bbaac3879f98adce89a8871706fe50dda03"

match_1 = json_fingerprint.match(input=json_1, target_fingerprint=target_fp)
match_2 = json_fingerprint.match(input=json_2, target_fingerprint=target_fp)

print(f"Fingerprint matches with json_1: {
      
      match_1}")
print(f"Fingerprint matches with json_2: {
      
      match_2}")

这将输出以下内容:

Fingerprint matches with json_1: True
Fingerprint matches with json_2: False

猜你喜欢

转载自blog.csdn.net/ymzhu385/article/details/138715337