我的目录中有一些Yaml文件。如何将它们全部加载到同一个YAML对象(地图)中?
# a.yaml
a: ValueA
c: ValueC
# b.yaml
a: ValueAA
b: ValueB
我要a.yaml,然后是b.yaml。结果将是:
{ a: ValueAA, b: ValueB, c: ValueC }
我可以这样做的一种方法是将a.yaml和b.yaml的内容显式连接到单个String中,然后加载合并的String。我想知道是否可以避免这种情况,只需使用load()API依次加载2个yaml文件即可。
答案 0 :(得分:1)
我不知道SnakeYAML的详细信息,但是即使两个文件a.yaml
和b.yaml
在根级别都有映射,您也不能将它们串联在一起。
这样一来,您将在映射中获得重复键,并且根据YAML 1.2(和1.0)规范,您将不具有重复键,而1.1规范指出您应在重复键和第一个值上得到警告(您表示您想拥有第二个)。
因此,您必须使用Java来解决此问题,可以通过从相应文件中加载文档并用a.yaml
中的文件更新从b.yaml
中加载的数据结构来实现。
您还可以将文件串联到包含多个文档的文件中,但是为此,必须使用指令末尾指示符(---
)或文档末尾指示符({{ 1}})。通常,您需要使用特殊的“全部加载”功能来加载这样的多文档文件,从而生成从映射加载的数据结构列表(或迭代器),然后可以合并。
如果您以编程方式制作多文档文件,请确保检查文件是否以换行符结尾,否则请附加...
并且下一个文件将无法提供您期望的多文档流。 / p>
答案 1 :(得分:1)
有关详细信息,请参阅Anthon的答案。作为仅供参考的FYI,我就是这样做的。
final Yaml yaml = new Yaml(configConstructor, representer);
try (
final InputStream defaultYamlStream = new FileInputStream(settingsPath + "/cbench-default.yaml");
final InputStream customerYamlStream = new FileInputStream(settingsPath + "/" + identifier + ".yaml");
final InputStream fullYamlStream = new SequenceInputStream(defaultYamlStream, customerYamlStream);
) {
//try
parsedConfig = (BenchmarkConfig) yaml.load(fullYamlStream);
} catch (IOException ioe) {
// ERROR
System.out.println("Exception parsing the YAML configuration.");
throw new RuntimeException("Exception parsing the YAML configuration.", ioe);
}
我正在创建级联文件流(在我的情况下为序列流),并按照Anthon的建议使用load API,它工作正常。记下文档结束标记。
答案 2 :(得分:0)
下面是一个使用小型递归函数(用Groovy编写)的示例:
@Grapes(
@Grab(group='org.yaml', module='snakeyaml', version='1.25')
)
import org.yaml.snakeyaml.Yaml
import static groovy.json.JsonOutput.prettyPrint
import static groovy.json.JsonOutput.toJson
def extension = new Yaml().load(("extension.yml" as File).text)
def original = new Yaml().load(("original.yml" as File).text)
println prettyPrint(toJson(original))
println "#############################"
iterateAndOverrite(extension, original)
extension = original
println prettyPrint(toJson(original))
private void iterateAndOverrite(extension, original){
extension.each {
if(it.value instanceof Map && original[it.key] != null){
iterateAndOverrite(extension[it.key], original[it.key])
} else {
original[it.key] = extension[it.key]
}
}
}