scala 如何在 Typesafe Config 中获得解包的密钥?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21738023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:04:10  来源:igfitidea点击:

How do I get an unwrapped key in Typesafe Config?

scalatypesafetypesafe-config

提问by Chad Retz

Test case:

测试用例:

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"
  }
}

This test fails because the key is actually "quoted.key.1", not quoted.key.1. Is there a suggested way to unwrap this or do I have to manually look for surrounding quotes and remove them every time?

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

采纳答案by Havoc P

Read about "Paths, keys, and Config vs. ConfigObject" in the API docs here: http://typesafehub.github.io/config/latest/api/com/typesafe/config/Config.htmland in the README here: https://github.com/typesafehub/config#understanding-config-and-configobject

在此处的 API 文档中阅读“路径、密钥和配置与 ConfigObject”:http: //typesafehub.github.io/config/latest/api/com/typesafe/config/Config.html和此处的自述文件:https://github.com/typesafehub/config#understanding-config-and-configobject

(Suggestions for improving those docs are welcome.)

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

The keys in the entry set (and the Config) are path expressions. These are strings that require parsing. There is a parse method in ConfigUtil, see http://typesafehub.github.io/config/latest/api/com/typesafe/config/ConfigUtil.html#splitPath%28java.lang.String%29

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

It won't work to just remove quotes, the parsing is somewhat more complex than that. Fortunately you can just use the ConfigUtil.splitPathmethod.

仅删除引号是行不通的,解析比这要复杂一些。幸运的是,您可以使用该ConfigUtil.splitPath方法。

So the two ways to iterate keys at the root level are something like, first with Config:

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

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

Then with ConfigObject:

然后使用 ConfigObject:

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

I didn't try compiling the above examples so forgive any silly syntax errors.

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

If your configuration contains only one level (no nested objects) the above two ways of iterating are the same; but if you have nested values they are not the same because iterating Configwill give you all leafvalues while iterating ConfigObject(config.root()) will give you all immediate children of the root, even if those immediate children are themselves objects.

如果你的配置只包含一层(没有嵌套对象),上面两种迭代方式是一样的;但是如果你有嵌套的值,它们就不一样了,因为迭代Config会给你所有的叶子值,而迭代ConfigObjectconfig.root())会给你根的所有直接子元素,即使这些直接子元素本身就是对象。

Say you have:

说你有:

foo {
   bar {
       baz = 10
   }
}

If you iterate that as a Configyou will get oneentry which will have the path foo.bar.bazas key and the value 10. If you iterate it as a ConfigObjectthen you will have one entry which will have the key fooand the value will be an object which will in turn contain the key bar. When iterating this as a Configyou could splitPaththe foo.bar.bazand you would get an array of three strings, foo, bar, and baz.

如果您Config将其作为 a 进行迭代,您将获得一个条目,该条目将路径foo.bar.baz作为 key 和 value 10。如果您将其作为 a 进行迭代,ConfigObject那么您将拥有一个包含键的条目,foo而值将是一个对象,该对象又将包含键bar。当迭代这是一个Config你可以splitPathfoo.bar.baz,你会得到三个字符串,数组foobarbaz

To convert a Configto a ConfigObjectuse the root()method and to convert ConfigObjectto Configuse the toConfig()method. So config.root().toConfig() == config.

要转换ConfigConfigObject使用root()方法,并转换ConfigObjectConfig使用toConfig()方法。所以config.root().toConfig() == config

Also, the above config file could be equivalently written as:

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

foo.bar.baz = 10

But would be different if written as:

但如果写成:

"foo.bar.baz" = 10

Because in the first case you have nested objects, and in the second case you have a single object with periods in the key name. This is due to the quotes.

因为在第一种情况下,您有嵌套的对象,而在第二种情况下,您有一个键名中带有句点的对象。这是由于引号引起的。

If you write "foo.bar.baz"with quotes, then when iterating Configthe path you got back would be quoted and splitPath()would return an array of one element foo.bar.baz. When iterating ConfigObjectyou would have a single object which would contain an entry with foo.bar.bazas key and 10as value. Keys containing ., or other special characters, have to be quoted so they are interpreted as single keys rather than as paths.

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

To make your test case pass you could do this using splitPath:

要使您的测试用例通过,您可以使用 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"
  }
}

You could also do this, using ConfigObject:

你也可以这样做,使用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"
  }
}

回答by zeromem

in java, first unwarp the whole ConfigObjectto a hashmap, then you can use quoted.key.1(without surrounding quotes) as key to get correct value.

在 java 中,首先将整个解压缩ConfigObject为一个哈希图,然后您可以使用quoted.key.1(不带引号)作为获得正确值的键。