如何在Typesafe配置中获取未包装的密钥?

时间:2014-02-12 19:43:59

标签: scala typesafe typesafe-config

测试用例:

import org.specs2.mutable._
class HelloWorldSpec extends Specification {
  "Typesafe Config" should "allow me to see my escaped key" in {
    val entries = ConfigFactory.parseString("""
      "quoted.key.1" = 5
      "quoted.key.2" = 6""").entrySet
    entries.head.getKey === "quoted.key.1"
  }
}

此测试失败,因为密钥实际上是"quoted.key.1",而不是quoted.key.1。是否有建议的方法解开这个或我是否必须手动查找周围的引号并每次删除它们?

2 个答案:

答案 0 :(得分:8)

在此处的API文档中了解“路径,键和Config与ConfigObject”:http://typesafehub.github.io/config/latest/api/com/typesafe/config/Config.html 在这里的自述文件中:https://github.com/typesafehub/config#understanding-config-and-configobject

(欢迎提出改进这些文档的建议。)

条目集(和Config)中的键是路径表达式。这些是需要解析的字符串。 ConfigUtil中有一个解析方法,请参阅http://typesafehub.github.io/config/latest/api/com/typesafe/config/ConfigUtil.html#splitPath%28java.lang.String%29

仅删除引号不起作用,解析比这更复杂。幸运的是,您可以使用ConfigUtil.splitPath方法。

因此,在根级别迭代键的两种方法类似于,首先使用Config:

Config config = ... ;
for (Map.Entry<String, ConfigValue> entry: config.entrySet()) {
  String[] keys = ConfigUtil.splitPath(entry.getKey());
  System.out.println("Root key = " + keys[0]);
}

然后使用ConfigObject:

Config config = ... ;
for (Map.Entry<String, ConfigValue> entry: config.root().entrySet()) {
  System.out.println("Root key = " + entry.getKey());
}

我没有尝试编译上面的例子,所以请原谅任何愚蠢的语法错误。

如果您的配置只包含一个级别(没有嵌套对象),则上述两种迭代方式是相同的;但是如果你有嵌套值,它们就不一样了,因为迭代Config将为你提供所有 leaf 值,而迭代ConfigObjectconfig.root())将立即给你所有根的孩子,即使那些直接的孩子本身也是对象。

说你有:

foo {
   bar {
       baz = 10
   }
}

如果您将其作为Config进行迭代,则会获得一个条目,该条目的路径为foo.bar.baz作为键,值为10。如果您将其作为ConfigObject进行迭代,那么您将拥有一个具有密钥foo的条目,该值将是一个对象,而该对象又包含密钥bar。当您将Config作为splitPath进行迭代时,foo.bar.baz foo可以得到一个包含三个字符串的数组,barbaz和{{1} }。

要将Config转换为ConfigObject,请使用root()方法并将ConfigObject转换为Config,并使用toConfig()方法。所以config.root().toConfig() == config

此外,上述配置文件可以等效地写为:

foo.bar.baz = 10

但如果写成:

会有所不同
"foo.bar.baz" = 10

因为在第一种情况下你有嵌套对象,而在第二种情况下,你有一个在键名中有句点的对象。这是由于报价。

如果您使用引号编写"foo.bar.baz",则在迭代Config时,将引用您返回的路径,splitPath()将返回一个元素foo.bar.baz的数组。迭代ConfigObject时,您将拥有一个对象,其中包含一个以foo.bar.baz为键,10为值的条目。必须引用包含.或其他特殊字符的键,以便将它们解释为单个键而不是路径。

要使测试用例通过,您可以使用splitPath执行此操作:

import org.specs2.mutable._
class HelloWorldSpec extends Specification {
  "Typesafe Config" should "allow me to see my escaped key" in {
    val entries = ConfigFactory.parseString("""
      "quoted.key.1" = 5
      "quoted.key.2" = 6""").entrySet
    // the ordering of entrySet is not guaranteed so this may
    // still fail because it gets quoted.key.2 instead
    ConfigUtil.splitPath(entries.head.getKey).head === "quoted.key.1"
  }
}

您也可以使用ConfigObject

执行此操作
import org.specs2.mutable._
class HelloWorldSpec extends Specification {
  "Typesafe Config" should "allow me to see my escaped key" in {
    val entries = ConfigFactory.parseString("""
      "quoted.key.1" = 5
      "quoted.key.2" = 6""").root.entrySet // note ".root." here
    // the ordering of entrySet is not guaranteed so this may
    // still fail because it gets quoted.key.2 instead
    // no need to splitPath because ConfigObject has keys not paths
    entries.head.getKey === "quoted.key.1"
  }
}

答案 1 :(得分:0)

在Java中,首先将整个ConfigObject取消变形为哈希图,然后可以使用quoted.key.1(不带引号)作为获取正确值的键。