在保留注释的同时在 java 中修改 YAML
Posted
技术标签:
【中文标题】在保留注释的同时在 java 中修改 YAML【英文标题】:Modifying YAML in java while preserving comments 【发布时间】:2018-09-23 12:29:06 【问题描述】:我们如何修改现有的 YAML 并在其中保留 cmets。 是否有任何 Java 解析器可以做到这一点? 例如,如果我有以下 YAML:
#This is a test YAML
name: abcd
age: 23
#Test YAML ends here.
有没有办法可以使用 java 解析器编辑这个 Yaml 并保留 cmets。
【问题讨论】:
你吃过蛇山药吗?默认不支持吗? 【参考方案1】:如果你使用snakeyaml,你应该修改ScannerImpl文件。
注意:将内嵌注释读取为文本
private Token scanPlain()
StringBuilder chunks = new StringBuilder();
Mark startMark = reader.getMark();
Mark endMark = startMark;
int indent = this.indent + 1;
String spaces = "";
while (true)
int c;
int length = 0;
// A comment indicates the end of the scalar.
// read the in-line comment as text
// if (reader.peek() == '#' && )
// break;
//
while (true)
c = reader.peek(length);
if (Constant.NULL_BL_T_LINEBR.has(c)
|| (c == ':' && Constant.NULL_BL_T_LINEBR.has(reader.peek(length + 1), flowLevel != 0 ? ",[]":""))
|| (this.flowLevel != 0 && ",?[]".indexOf(c) != -1))
break;
length++;
if (length == 0)
break;
this.allowSimpleKey = false;
chunks.append(spaces);
chunks.append(reader.prefixForward(length));
endMark = reader.getMark();
spaces = scanPlainSpaces();
// System.out.printf("spaces[%s]\n", spaces);
if (spaces.length() == 0
// read the in-line comment as text
// || reader.peek() == '#'
|| (this.flowLevel == 0 && this.reader.getColumn() < indent))
break;
return new ScalarToken(chunks.toString(), startMark, endMark, true);
【讨论】:
【参考方案2】:我写了一个 groovy 脚本来解决这个问题。 Java 版本非常相似:
def key = "name"
def value = "efgh"
def yamlFile = new File("file.yaml")
def yamlFileLines = new StringBuilder()
def foundKey = false
yamlFile.text.eachLine line ->
if (!foundKey && line.contains("$key:"))
line = line.replaceAll(/$key:.*/, "$key: $value")
foundKey = true
yamlFileLines.append("$line\n")
if (foundKey)
yamlFile.text = yamlFileLines.toString()
else
throw new StopExecutionException("Could not find key '$key' in file $yamlFile.getAbsolutePath()")
【讨论】:
【参考方案3】:截至撰写本文时,还没有适用于 Java 的往返 YAML 解析器。有著名的SnakeYAML,它不保留cmets(参见author's comment here),还有一个名为camel的较新项目,我对此知之甚少;但绝对不是往返。
理论上你可以做的是使用 SnakeYaml 的 Yaml.parse
然后遍历事件。每个事件都有一个开始和一个结束标记,给出了事件的开始和结束行和列。这使得将事件映射回源并发现源中未解析为事件的部分(可能是 cmets)成为可能。有了这个映射,您现在可以修改事件列表并将其写回。最后,您再次阅读结果,发现原始 YAML 中存在 cmets 而修改后的 YAML 中没有的事件之间的差距,然后重新插入这些 cmets,为您提供修改后的最终 YAML 和 cmets。
当然,这是非常复杂的。我不建议这样做,除非你 a) 对 YAML 的结构有深刻的理解或愿意学习它,并且 b) 你的用例证明了这么多工作是合理的。
【讨论】:
以上是关于在保留注释的同时在 java 中修改 YAML的主要内容,如果未能解决你的问题,请参考以下文章