在此处的 API 文档中阅读“路径、键和 Config 与 ConfigObject”:http://typesafehub.github.io/config/latest/api/com/typesafe/config/Config.html
并在此处的自述文件中:https://github.com/typesafehub/config#understanding-config-and-configobject
(欢迎提出改进这些文档的建议。)
入口集(和配置)中的键是路径表达式。这些是需要解析的字符串。 ConfigUtil中有parse方法,见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 值,而迭代 ConfigObject (config.root()) 会给你根的所有直接子节点,甚至如果这些直系孩子本身就是对象。
假设你有:
foo {
bar {
baz = 10
}
}
如果您将其作为Config 进行迭代,您将获得一个 条目,其中路径foo.bar.baz 作为键,值10。如果您将其作为ConfigObject 进行迭代,那么您将拥有一个条目,该条目将具有键foo,而值将是一个对象,该对象又将包含键bar。当将其迭代为 Config 时,您可以将 splitPath foo.bar.baz 进行迭代,您将得到一个包含三个字符串的数组,foo、bar 和 baz。
要将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"
}
}