2017-07-03 99 views
1

我试图使用Groovy和Snakeyaml(显然我已经消毒的数据,但它足以说明问题)来解析以下YAML文件:Snakeyaml出现在列表中不必要的包装简单值

--- 
info: 
    summary: Snakeyaml Issue 
examples: 
    - 1st example: 
     name: Example 1 
     sublist: 
     - 0.1: 
      foo: bar 

我期望以下语句:

println resource.info.summary 
println resource.examples."1st example".name 
println resource.examples."1st example".sublist."0.1" 

产生:

Snakeyaml Issue 
Example 1 
[foo:bar] 

和:

println resource.examples."1st example".sublist."0.1".foo 

产生:

bar 

然而,从实际输出:

println resource.info.summary 
println resource.examples."1st example".name 
println resource.examples."1st example".sublist."0.1" 
println resource.examples."1st example".sublist."0.1".foo 

是:

Snakeyaml Issue 
[Example 1] 
[[[foo:bar]]] 
[[bar]] 

我只能得到欲望d输出包括列表标记:

println resource.info.summary 
println resource.examples[0]."1st example".name 
println resource.examples[0]."1st example".sublist[0]."0.1" 
println resource.examples[0]."1st example".sublist[0]."0.1".foo 

这似乎是不必要的。也许我误解了数据的结构?

为了完整起见,我使用来说明这一问题的常规代码如下所示(我抓起CustomerResolver码断网,使其将保持浮动字符串):

import org.yaml.snakeyaml.DumperOptions 
import org.yaml.snakeyaml.Yaml 
import org.yaml.snakeyaml.constructor.Constructor 
import org.yaml.snakeyaml.nodes.Tag 
import org.yaml.snakeyaml.representer.Representer 
import org.yaml.snakeyaml.resolver.Resolver 

def fileName = "example.yaml" 
def Yaml yaml = new Yaml(new Constructor(), new Representer(), new DumperOptions(), 
    new CustomResolver()) 
def resource = yaml.load(new File(fileName).newInputStream()) 

println resource.info.summary 
println resource.examples."1st example".name 
println resource.examples."1st example".sublist."0.1" 
println resource.examples."1st example".sublist."0.1".foo 

class CustomResolver extends Resolver { 

    /* 
    * Do not resolve float and timestamp 
    */ 

    protected void addImplicitResolvers() { 
     addImplicitResolver(Tag.BOOL, BOOL, "yYnNtTfFoO"); 
     addImplicitResolver(Tag.INT, INT, "-"); 
     addImplicitResolver(Tag.MERGE, MERGE, "<"); 
     addImplicitResolver(Tag.NULL, NULL, "~nN\0"); 
     addImplicitResolver(Tag.NULL, EMPTY, null); 

    } 
} 

任何想法?

+0

由于'sublist'的值是一个序列,所以你不需要指出你想要的元素。现在只有一个元素是不能保证永远不会有。我期望'println resource.examples。“第一个例子”.sublist。“0.1”.foo'引发错误。 – Anthon

+0

在你的第8个代码块中,BTW不应该是'“0.1”'而不是'“blah”'? – Anthon

+0

谢谢@Anthon。我纠正了“blah”错误(我将其重命名为0.1以便在本地删除,并删除了CustomResolver以查看是否是该问题,并在编辑时意外地将其保留);好点。 我想我现在明白了。 **子列表**包含一系列地图,其中第一个具有** 0.1 **作为键和地图** foo:bar **作为值? – Simon

回答

1

你如何访问YAML的方式问题

examples第一个包含list,然后才包含object与关键1st example

您的情况下,尝试这种访问:

println resource.info.summary 
println resource.examples[0]."1st example" 
println resource.examples[0]."1st example".name 
println resource.examples[0]."1st example".sublist[0] 
println resource.examples[0]."1st example".sublist[0]."0.1" 
println resource.examples[0]."1st example".sublist[0]."0.1".foo 

到了解列表访问器如何工作检查此示例:

@Grab(group='org.yaml', module='snakeyaml', version='1.18') 
import org.yaml.snakeyaml.Yaml 

def Yaml yaml = new Yaml() 
def resource = yaml.load(new StringReader('''--- 
info: 
    summary: Snakeyaml Issue 
examples: 
    - 1st example: 
     name: Example 1 
    - 1st example: 
     name: Example 2 
    - 1st example: 
     xname: Example 3 
    - 2nd example: 
     name: Example 4 
''')) 

println resource.examples."1st example" 
//prints> [[name:Example 1], [name:Example 2], [xname:Example 3], null] 

println resource.examples."1st example".name 
//prints> [Example 1, Example 2, null] 
+0

这是一个非常好的例子。谢谢@daggett。它现在有意义 – Simon

+0

@daggett你知道如果创建一个列表,当在正确的地方排除序列索引时,它是一个特征吗?你真的可以做'println resource.examples。“第一个例子”.sublist。“0.1”.foo [0] [0]'得到'bar'吗? – Anthon

+1

是的,你可以做到这一点,但至于我更好的解开他们出现的地方阵列。 – daggett