如何从同一个YAML文件中的其他地方引用YAML"设置"?

And*_*ock 118 syntax yaml transclusion

我有以下YAML:

paths:
  patha: /path/to/root/a
  pathb: /path/to/root/b
  pathc: /path/to/root/c
Run Code Online (Sandbox Code Playgroud)

如何通过/path/to/root/从三个路径中删除并将其作为自己的设置来"规范化" ,例如:

paths:
  root: /path/to/root/
  patha: *root* + a
  pathb: *root* + b
  pathc: *root* + c
Run Code Online (Sandbox Code Playgroud)

显然这是无效的,我只是弥补了.什么是真正的语法?可以吗?

vav*_*ava 105

我不认为这是可能的.您可以重用"节点"但不能重用它.

bill-to: &id001
    given  : Chris
    family : Dumars
ship-to: *id001
Run Code Online (Sandbox Code Playgroud)

这是完全有效的YAML和字段given,family可以在ship-to块中重复使用.您可以以相同的方式重用标量节点,但是您无法更改内部的内容并从YAML内部添加路径的最后一部分.

如果重复打扰你那么多我建议让你的应用程序知道root属性并将其添加到看起来相对而非绝对的每个路径.

  • 接受的答案并不准确.请参阅我的答案以获得解决方案 (2认同)
  • 参见 http://yaml.org/spec/1.2/spec.html 中的示例 2.9;还可以参考标量,这很棒 (2认同)

Chr*_*son 67

是的,使用自定义标签.Python中的示例,使!join标记连接数组中的字符串:

import yaml

## define custom tag handler
def join(loader, node):
    seq = loader.construct_sequence(node)
    return ''.join([str(i) for i in seq])

## register the tag handler
yaml.add_constructor('!join', join)

## using your sample data
yaml.load("""
paths:
    root: &BASE /path/to/root/
    patha: !join [*BASE, a]
    pathb: !join [*BASE, b]
    pathc: !join [*BASE, c]
""")
Run Code Online (Sandbox Code Playgroud)

结果如下:

{
    'paths': {
        'patha': '/path/to/root/a',
        'pathb': '/path/to/root/b',
        'pathc': '/path/to/root/c',
        'root': '/path/to/root/'
     }
}
Run Code Online (Sandbox Code Playgroud)

参数数组!join可以包含任意数据类型的任意数量的元素,只要它们可以转换为字符串,!join [*a, "/", *b, "/", *c]您所期望的也是如此.

  • 这个答案值得更多的投票.从技术上讲,它是YAML规范中最准确的答案.但是,有一点需要注意,根据实际的YAML*实现*,很少有实际实现完整的YAML规范.Python的pyyaml在规范的一致性方面超越了许多其他人. (4认同)
  • 我喜欢你的解决方案,编码更简单,但代价是 YAML 可读性稍差。 (2认同)
  • 谁对此表示反对-您能说为什么吗? (2认同)
  • 问题似乎与在yaml文件中引用值有关。在它周围添加另一层代码不是我的首选解决方案。 (2认同)
  • 这个解决方案不适用于我(`python3`?),但是对上面的内容进行了简单的修改就可以按预期工作。具体来说:yaml.SafeLoader.add_constructor(tag ='!join',Constructor = join)`yaml.load(open(fpth,mode ='r'),Loader = yaml.SafeLoader) (2认同)

Bri*_*man 17

另一种看待这种情况的方法是简单地使用另一个字段.

paths:
  root_path: &root
     val: /path/to/root/
  patha: &a
    root_path: *root
    rel_path: a
  pathb: &b
    root_path: *root
    rel_path: b
  pathc: &c
    root_path: *root
    rel_path: c
Run Code Online (Sandbox Code Playgroud)


小智 6

我创建了一个可在 Packagist 上使用的库,用于执行此功能:https ://packagist.org/packages/grasmash/yaml-expander

YAML 文件示例:

type: book
book:
  title: Dune
  author: Frank Herbert
  copyright: ${book.author} 1965
  protaganist: ${characters.0.name}
  media:
    - hardcover
characters:
  - name: Paul Atreides
    occupation: Kwisatz Haderach
    aliases:
      - Usul
      - Muad'Dib
      - The Preacher
  - name: Duncan Idaho
    occupation: Swordmaster
summary: ${book.title} by ${book.author}
product-name: ${${type}.title}
Run Code Online (Sandbox Code Playgroud)

示例逻辑:

// Parse a yaml string directly, expanding internal property references.
$yaml_string = file_get_contents("dune.yml");
$expanded = \Grasmash\YamlExpander\Expander::parse($yaml_string);
print_r($expanded);
Run Code Online (Sandbox Code Playgroud)

结果数组:

array (
  'type' => 'book',
  'book' => 
  array (
    'title' => 'Dune',
    'author' => 'Frank Herbert',
    'copyright' => 'Frank Herbert 1965',
    'protaganist' => 'Paul Atreides',
    'media' => 
    array (
      0 => 'hardcover',
    ),
  ),
  'characters' => 
  array (
    0 => 
    array (
      'name' => 'Paul Atreides',
      'occupation' => 'Kwisatz Haderach',
      'aliases' => 
      array (
        0 => 'Usul',
        1 => 'Muad\'Dib',
        2 => 'The Preacher',
      ),
    ),
    1 => 
    array (
      'name' => 'Duncan Idaho',
      'occupation' => 'Swordmaster',
    ),
  ),
  'summary' => 'Dune by Frank Herbert',
);
Run Code Online (Sandbox Code Playgroud)


小智 5

YML定义:

dir:
  default: /home/data/in/
  proj1: ${dir.default}p1
  proj2: ${dir.default}p2
  proj3: ${dir.default}p3 
Run Code Online (Sandbox Code Playgroud)

在百里香的某个地方

<p th:utext='${@environment.getProperty("dir.default")}' />
<p th:utext='${@environment.getProperty("dir.proj1")}' /> 
Run Code Online (Sandbox Code Playgroud)

输出: / home/data/in// home/data/in/p1

  • 不,它不是YAML中变量的本机用法,并且未在任何规范版本中指定.经过一些测试,这不起作用. (3认同)
  • 这可能对Pavol使用预处理过的yaml的东西有效(例如,maven-resources-plugin过滤) (2认同)
  • 不是标准的 Yaml (2认同)

Art*_*ste 5

在某些语言中,您可以使用替代库,例如,tampax是 YAML 处理变量的实现:

const tampax = require('tampax');

const yamlString = `
dude:
  name: Arthur
weapon:
  favorite: Excalibur
  useless: knife
sentence: "{{dude.name}} use {{weapon.favorite}}. The goal is {{goal}}."`;

const r = tampax.yamlParseString(yamlString, { goal: 'to kill Mordred' });
console.log(r.sentence);

// output : "Arthur use Excalibur. The goal is to kill Mordred."
Run Code Online (Sandbox Code Playgroud)

编者注:海报也是这个包的作者。