Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
支持继承的YAML或JSON库_Json_Jackson_Yaml - Fatal编程技术网

支持继承的YAML或JSON库

支持继承的YAML或JSON库,json,jackson,yaml,Json,Jackson,Yaml,我们正在建立一个服务。它必须从文件中读取配置。我们目前正在使用YAML和Jackson来反序列化YAML。我们的YAML文件需要继承/扩展另一个YAML文件。例如,类似于: extends: base.yaml appName: my-awesome-app ... 因此,部分配置存储在base.yaml中。是否有支持此功能的库?如果允许从多个文件继承,则可获得额外点数。我们可以改为使用JSON而不是YAML。JSON和YAML都不能包含文件。无论您做什么,都将是一个预处理步骤,您将把ba

我们正在建立一个服务。它必须从文件中读取配置。我们目前正在使用YAML和Jackson来反序列化YAML。我们的YAML文件需要继承/扩展另一个YAML文件。例如,类似于:

extends: base.yaml

appName: my-awesome-app

...

因此,部分配置存储在
base.yaml
中。是否有支持此功能的库?如果允许从多个文件继承,则可获得额外点数。我们可以改为使用JSON而不是YAML。

JSON和YAML都不能包含文件。无论您做什么,都将是一个预处理步骤,您将把
base.yaml
和实际文件放在一起

一种粗略的方法是:

#include base.yaml
appName: my-awesome-app
这是你的档案。加载时,首先读取第一行,如果它以
#include
开头,则用包含文件的内容替换它。您需要递归地执行此操作。这基本上就是C预处理器对C文件所做的,包括

缺点是:

  • 即使两个文件都是有效的YAML,结果也可能不是
  • 如果其中一个文件包含指令结束或文档结束标记(
    --
    ..
    ),则一个文件中将包含两个单独的文档
  • 无法替换文件中
    base.yaml
    中的任何值
因此,另一种选择是实际操作YAML结构。为此,您需要YAML解析器的API(在您的例子中是SnakeYAML)并用它解析您的文件。您应该使用compose API:

private Node preprocess(final Reader myInput) {
    final Yaml yaml = new Yaml();
    final Node node = yaml.compose(myInput);
    processIncludes(node);
    return node;
}

private void processIncludes(final Node node) {
    if (node instanceof MappingNode) {
        final List<NodeTuple> values = ((MappingNode) node).getValue();
        for (final NodeTuple tuple: values) {
            if ("!include".equals(tuple.getKeyNode().getTag().getValue())) {
                final String includedFilePath =
                        ((ScalarNode) tuple.getValueNode()).getValue();
                final Node content = preprocess(new FileReader(includedFilePath));
                // now merge the content in your preferred way into the values list.
                // that will change the content of the node.
            }
        }
    }
}

public String executePreprocessor(final Reader source) {
    final Node node = preprocess(source);
    final StringWriter writer = new StringWriter();
    final DumperOptions dOptions = new DumperOptions()
    Serializer ser = new Serializer(new Emitter(writer, dOptions),
                                    new Resolver(), dOptions, null);
    ser.open();
    ser.serialize(node);
    ser.close();
    return writer.toString();
}
我使用了私有标签
!包括
,以便不会与任何法线映射键发生名称冲突。注意
后面的空格!包括
。我没有给出合并包含文件的代码,因为我不知道您希望如何处理重复的映射键。但实施起来应该不难。注意bug,我还没有测试过这段代码


生成的字符串可以作为Jackson的输入。

可能出于同样的目的,我创建了这个工具:

您可以通过以下语法并结合
yq
命令来实现

extends: [ base.yaml ]

appName: my-awesome-app

...
请注意,您需要将要扩展的文件名放入数组中,因为该工具支持多重继承

您可能不喜欢的点包括

  • 速度有点慢。(但对于配置信息,这可能是可以的,因为您可以将其转换为扩展文件一次,并且在转换之后,您的系统将永远不会再转换为原始文件)
  • 数组中的对象无法按预期运行,因为该工具依赖于
    jq
    *
    运算符
具有
包含
语法
extends: [ base.yaml ]

appName: my-awesome-app

...
$ yq -j . your.yaml | jq-front | yq -y .