SnakeYAML 低级 API 没有正确解析 MapNode
SnakeYAML low-level API not parsing MapNode correctly
我想对 yml 文件中的值做一些处理。为此,有人建议我使用 snakeYAML 的 low-level API。所以我用它写了一些代码,但由于以下原因我几乎卡住了。
这是我写的代码:
public static void main(String[] args) throws Exception{
Yaml yaml = new Yaml();
FileReader contentFromFile=new FileReader("/Users/prakash.tiwari/Desktop/yamlInput.yml");
for (Node node : yaml.composeAll(contentFromFile)) {
System.out.println(node);
}
}
这是我的 yamlInput.yml
:
Prakash:
Lucky:
Number: 11
Really? : NotAtAll
这是在控制台上打印的内容(它在一行中,我对其进行了格式化并添加了注释以使其可读):
<org.yaml.snakeyaml.nodes.MappingNode
(
tag=tag:yaml.org,2002:map,
values=
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Prakash)>;
value=355629945 // Why is this a garbage value?
}
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
value=
<NodeTuple
keyNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
valueNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=NotAtAll)>
>
}
)>
此时我可以通过搜索valueNode=<org.yaml.snakeyaml.nodes.ScalarNode
提取valueNode
也是ScalarNode
,然后处理这个节点中的值。
但问题是我不知道为什么它在组成地图节点时会放入垃圾值。所以这是我的问题:
- 如何正确编写 yaml 文件,使地图节点正确显示而不是垃圾值?
- 在我完成处理并成功将值替换为处理后的值后,如何将它们放回 yaml 文件?
- 如果您认为这是一个垃圾方法,请给我推荐一个更好的方法。
你得到“垃圾值”的原因是因为MappingValue
's toString method中的这个部分:
if (node.getValueNode() instanceof CollectionNode) {
// to avoid overflow in case of recursive structures
buf.append(System.identityHashCode(node.getValueNode()));
} else {
buf.append(node.toString());
}
由于组合图可能包含循环(因为锚点和别名已在解析的这个阶段解析),toString 不会递归到 Collection 节点(即映射和序列)。
这意味着您的节点树确实已正确组成,您根本不应该使用 toString
来检查它。这回答了你的第一个问题。
要将其写回 YAML 文件,请使用
Emitter emitter = new Emitter(/* e.g. a FileWriter */ writer, new DumperOptions());
for (Event event : yaml.serialize(/* the root node */ node)) {
emitter.emit(event);
}
回答问题 3:在上一个问题中,您提到要更改(加密)某些值并保持其他值不变。如果是这种情况,我建议您使用 yaml.parse
而不是 yaml.compose
,因为在处理事件流时丢失的信息比处理组合图时丢失的信息少(这意味着输出将更类似于输入)。
然后您可以查看生成的事件,确定要更改的事件并将它们替换为更改后的事件,然后使用我在上面的代码中显示的发射器。
我展示了一些 Python 代码 如何从字符串列表(一种“YAML 路径”)中识别事件流中的事件,但是该代码将事件插入到给定的路径而不是改变它们。 Python 和 Java API 有点相似,所以如果你能阅读 Python,该代码可能会对你有所帮助。
我想对 yml 文件中的值做一些处理。为此,有人建议我使用 snakeYAML 的 low-level API。所以我用它写了一些代码,但由于以下原因我几乎卡住了。
这是我写的代码:
public static void main(String[] args) throws Exception{
Yaml yaml = new Yaml();
FileReader contentFromFile=new FileReader("/Users/prakash.tiwari/Desktop/yamlInput.yml");
for (Node node : yaml.composeAll(contentFromFile)) {
System.out.println(node);
}
}
这是我的 yamlInput.yml
:
Prakash:
Lucky:
Number: 11
Really? : NotAtAll
这是在控制台上打印的内容(它在一行中,我对其进行了格式化并添加了注释以使其可读):
<org.yaml.snakeyaml.nodes.MappingNode
(
tag=tag:yaml.org,2002:map,
values=
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Prakash)>;
value=355629945 // Why is this a garbage value?
}
{
key=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
value=
<NodeTuple
keyNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=Really?)>;
valueNode=<org.yaml.snakeyaml.nodes.ScalarNode (tag=tag:yaml.org,2002:str, value=NotAtAll)>
>
}
)>
此时我可以通过搜索valueNode=<org.yaml.snakeyaml.nodes.ScalarNode
提取valueNode
也是ScalarNode
,然后处理这个节点中的值。
但问题是我不知道为什么它在组成地图节点时会放入垃圾值。所以这是我的问题:
- 如何正确编写 yaml 文件,使地图节点正确显示而不是垃圾值?
- 在我完成处理并成功将值替换为处理后的值后,如何将它们放回 yaml 文件?
- 如果您认为这是一个垃圾方法,请给我推荐一个更好的方法。
你得到“垃圾值”的原因是因为MappingValue
's toString method中的这个部分:
if (node.getValueNode() instanceof CollectionNode) {
// to avoid overflow in case of recursive structures
buf.append(System.identityHashCode(node.getValueNode()));
} else {
buf.append(node.toString());
}
由于组合图可能包含循环(因为锚点和别名已在解析的这个阶段解析),toString 不会递归到 Collection 节点(即映射和序列)。
这意味着您的节点树确实已正确组成,您根本不应该使用 toString
来检查它。这回答了你的第一个问题。
要将其写回 YAML 文件,请使用
Emitter emitter = new Emitter(/* e.g. a FileWriter */ writer, new DumperOptions());
for (Event event : yaml.serialize(/* the root node */ node)) {
emitter.emit(event);
}
回答问题 3:在上一个问题中,您提到要更改(加密)某些值并保持其他值不变。如果是这种情况,我建议您使用 yaml.parse
而不是 yaml.compose
,因为在处理事件流时丢失的信息比处理组合图时丢失的信息少(这意味着输出将更类似于输入)。
然后您可以查看生成的事件,确定要更改的事件并将它们替换为更改后的事件,然后使用我在上面的代码中显示的发射器。
我展示了一些 Python 代码