То, что вы хотите сделать, это "сжать" входные данные JSON в YAML со ссылками на те сопоставления, которые имеют точно такие же пары ключ-значение.Чтобы достичь этого, вам нужно найти такие сопоставления и один из способов сделать это - создать таблицу подстановки на основе строкового представления сопоставления после сортировки ключей .
*.1004 * Предполагая этот ввод 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, чтобы написать этот ответ на этом языке (не вкладывая слишком много усилий и не доставив некрасивого кода), но ОП, очевидно, понял намерение optmap()
и реализовал его в своего ответа