支持继承的YAML或JSON库
我们正在建立一个服务。它必须从文件中读取配置。我们目前正在使用YAML和Jackson来反序列化YAML。我们的YAML文件需要继承/扩展另一个YAML文件。例如,类似于:支持继承的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
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
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 .