您想要做的是将 JSON 输入“压缩”到 YAML 并引用那些映射
具有完全相同的键值对。为了实现这一目标,您需要能够找到
这种匹配映射和一种方法是通过创建一个基于
对键排序后的映射字符串表示。
假设这个 JSON 输入在 input.json:
{
"en": {
"models": {
"errors": {
"name": "name not found",
"url": "bad url"
}
},
"user": {
"errors": {
"name": "name not found",
"url": "bad url"
}
},
"photo": {
"errors": {
"name": "name not found",
"url": "bad url"
}
}
}
}
您可以使用此 Python 脚本将其转换为:
import json
import sys
from pathlib import Path
import ruamel.yaml
in_file = Path('input.json')
def optmap(d, mappings=None):
if mappings is None:
mappings = {}
if isinstance(d, dict):
for k in d:
v = d[k]
sv = repr(v)
ref = mappings.get(sv)
if ref is not None:
d[k] = ref
else:
mappings[sv] = v
optmap(d[k], mappings)
elif isinstance(d, list):
for idx, item in d:
sitem = repr(item)
ref = mappings.get(sitem)
if ref is not None:
d[idx] = sitem
else:
mappings[sitem] = item
optmap(item, mappings)
data = json.load(in_file.open())
optmap(data)
yaml = ruamel.yaml.YAML()
yaml.serializer.ANCHOR_TEMPLATE = u'%d'
yaml.dump(data, sys.stdout)
给出:
en:
models: &1
errors:
name: name not found
url: bad url
user: *1
photo: *1
上面还将引用和遍历 JSON 中的数组。
如您所见,您的输出可能会比实际情况更“压缩”。
我的 JavaScript 不够流利,无法用该语言编写此答案(无需投入太多精力并提供一些丑陋的代码),但 OP 显然理解 optmap() 的意图并在 his answer 中实现了它/p>