文章目录
由于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 函数(支持 SHA256、SHA384 和 SHA512)和 版本 (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