如何使用脚本中的引用压缩YAML文件?

时间:2019-04-23 08:48:21

标签: javascript yaml

我正在使用safeDump使用https://github.com/nodeca/js-yaml将json文件转换为YAML文件

结果是这样的

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

但是我希望脚本使用引用进行压缩

en:
  models: 
    errors: &1
      name: name not found
      url: bad url
  user:
    errors: *1
  photo:
    errors: *1

3 个答案:

答案 0 :(得分:1)

基于Anthon https://stackoverflow.com/a/55808583/10103951

的Python脚本
function buildRefsJson(inputJson, mappings = null) {
if (!mappings) {
    mappings = {}
}
if (typeof(inputJson) === 'object') {
    let value
    let stringValue
    let ref
    for (let key in inputJson) {
        value = inputJson[key]
        stringValue = JSON.stringify(value)
        ref = mappings[stringValue]
        if (ref) {
            inputJson[key] = ref
        } else {
            mappings[stringValue] = value
            buildRefsJson(inputJson[key], mappings)
        }
    }
}

我将其转换为JavaScript代码。它完成了工作!也感谢Niroj的帮助

答案 1 :(得分:0)

据我所知,遗憾的是,目前尚无解决方案可将具有引用的JSON转换为YML,因为在JSON中重复节点没有这种“引用”规则。正如spec所说,YAML因此可以看作是JSON的自然超集

答案 2 :(得分:0)

您要做的是使用对那些映射的引用将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()的意图并在{{ 3}}