以SnakeYAML为例 [英] SnakeYAML by example

查看:242
本文介绍了以SnakeYAML为例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 SnakeYAML 读取和解析YAML文件,并将其转换为配置POJO我的Java应用程序:

I am trying to read and parse a YAML file with SnakeYAML and turn it into a config POJO for my Java app:

// Groovy pseudo-code
class MyAppConfig {
    List<Widget> widgets
    String uuid
    boolean isActive

    // Ex: MyAppConfig cfg = new MyAppConfig('/opt/myapp/config.yaml')
    MyAppConfig(String configFileUri) {
        this(loadMap(configFileUri))
    }

    private static HashMap<String,HashMap<String,String>> loadConfig(String configFileUri) {
        Yaml yaml = new Yaml();
        HashMap<String,HashMap<String,String>> values
        try {
            File configFile = Paths.get(ClassLoader.getSystemResource(configUri).toURI()).toFile();
            values = (HashMap<String,HashMap<String,String>>)yaml.load(new FileInputStream(configFile));
        } catch(FileNotFoundException | URISyntaxException ex) {
            throw new MyAppException(ex.getMessage(), ex);
        }

        values
    }

    MyAppConfig(HashMap<String,HashMap<String,String>> yamlMap) {
        super()

        // Here I want to extract keys from 'yamlMap' and use their values
        // to populate MyAppConfig's properties (widgets, uuid, isActive, etc.).
    }
}

示例YAML:

widgets:
  - widget1
    name: blah
    age: 3000
    isSilly: true
  - widget2
    name: blah meh
    age: 13939
    isSilly: false
uuid: 1938484
isActive: false

因为它似乎出现了( ,SnakeYAML仅给了我一个HashMap<String,<HashMap<String,String>>来代表我的配置数据,所以看来我们只能拥有2个SnakeYAML支持的嵌套映射属性(外部映射和类型为<String,String>)的内部地图...

Since it appears that SnakeYAML only gives me a HashMap<String,<HashMap<String,String>> to represent my config data, it seems as though we can only have 2 nested mapped properties that SnakeYAML supports (the outer map and in the inner map of type <String,String>)...

  1. 但是,如果widgets包含一个列表/序列(例如fizzes),该列表/序列包含一个列表,例如buzzes,又包含另一个列表,等等?这仅仅是SnakeYAML的限制,还是我使用API​​的方式不正确?
  2. 要从此映射中提取值,我需要迭代其键/值,并且(似乎)需要应用我自己的自定义验证. SnakeYAML是否提供任何API进行提取和验证?例如,与其手动滚动我的代码来检查uuid是否是在地图内定义的属性,不如我可以做类似yaml.extract('uuid')之类的事情,这将是很好的.然后同上进行后续验证uuid(以及其他任何属性).
  3. YAML本身包含许多强大的概念,例如锚点和引用. SnakeYAML是否处理这些概念?如果最终用户在配置文件中使用它们,该怎么办-我应该如何检测/验证/执行它们?! SnakeYAML是否提供用于执行此操作的API?
  1. But what if widgets contains a list/sequence (say, fizzes) which contained a list of, say, buzzes, which contained yet another list, etc? Is this simply a limitation of SnakeYAML or am I using the API incorrectly?
  2. To extract values out of this map, I need to iterate its keys/values and (seemingly) need to apply my own custom validation. Does SnakeYAML provide any APIs for doing this extraction + validation? For instance, instead of hand-rolling my own code to check to see if uuid is a property defined inside the map, it would be great if I could do something like yaml.extract('uuid'), etc. And then ditto for the subsequent validation of uuid (and any other property).
  3. YAML itself contains a lot of powerful concepts, such as anchors and references. Does SnakeYAML handle these concepts? What if an end user uses them in the config file - how am I supposed to detect/validate/enforce them?!? Does SnakeYAML provide an API for doing this?

推荐答案

您的意思是这样的:

@Grab('org.yaml:snakeyaml:1.17')
import org.yaml.snakeyaml.*
import org.yaml.snakeyaml.constructor.*
import groovy.transform.*

String exampleYaml = '''widgets:
                       |  - name: blah
                       |    age: 3000
                       |    silly: true
                       |  - name: blah meh
                       |    age: 13939
                       |    silly: false
                       |uuid: 1938484
                       |isActive: false'''.stripMargin()

@ToString(includeNames=true)
class Widget {
    String name
    Integer age
    boolean silly
}

@ToString(includeNames=true)
class MyConfig {
    List<Widget> widgets
    String uuid
    boolean isActive

    static MyConfig fromYaml(yaml) {
        Constructor c = new Constructor(MyConfig)
        TypeDescription t = new TypeDescription(MyConfig)
        t.putListPropertyType('widgts', Widget)
        c.addTypeDescription(t);

        new Yaml(c).load(yaml)
    }
}

println MyConfig.fromYaml(exampleYaml)

显然,这是一个在Groovy控制台中运行的脚本,您不需要@Grab行,因为您可能已经在类路径中有了该库了;-)

Obviously, that's a script to run in the Groovy console, you wouldn't need the @Grab line, as you probably already have the library in your classpath ;-)

这篇关于以SnakeYAML为例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆