测试用例:
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"
}
}
该测试失败,因为 key 实际上是
"quoted.key.1"
,而不是quoted.key.1
。有没有建议的方法可以解开这个问题,还是我必须手动查找周围的引号并每次将其删除? 最佳答案
在此处阅读有关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
将为您提供所有叶值,而迭代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"
}
}
关于scala - 如何在Typesafe Config中获取未包装的 key ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21738023/