【问题标题】:HOCON array substitution from envs来自 envs 的 HOCON 数组替换
【发布时间】:2019-03-07 19:50:40
【问题描述】:

我使用的是 HOCON 配置格式,解析库来自 typesafe.Config。 HOCON 支持环境变量注入和覆盖。喜欢:

my.config = "asd"
my.config = ${?MY_ENV_VAR} 

如果存在名为 MY_ENV_VAR 的环境变量,这将替换默认值“asd”。但是我似乎找不到任何好的方法来替换列表环境。喜欢:

my.config = [1,2,3,4]
my.config = ${?MY_ENV_LIST}

因为默认情况下,来自外部的 env vars 将默认为字符串,因此从库的角度来看,[1,2,3,4] 将被视为“[1,2,3,4]”,因此不能将其视为列出并会产生如下运行时错误:

com.typesafe.config.ConfigException$WrongType: application.conf: 5: application.boolliststring 的类型为 STRING 而不是 LIST

在 com.typesafe.config.impl.SimpleConfig.findKey(SimpleConfig.java:133) 在 com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:145) 在 com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:151) 在 com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:159) 在 com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:164) 在 com.typesafe.config.impl.SimpleConfig.getList(SimpleConfig.java:212)

任何人都知道以 HOCON 格式进行列表 env 替换的正确方法是什么? 提前致谢。

【问题讨论】:

  • 环境变量MY_ENV_LIST 包含什么?
  • @ToYonos MY_ENV_LIST='[1,2,3,4]',来自环境变量。因为 env vars 只能是字符串类型,所以会导致这个问题。

标签: typesafe-config hocon


【解决方案1】:

答案

正如其他答案所说,从一个环境变量到数组是不可能开箱即用的。

您可以重新解析从配置加载的字符串:

// application.conf
my.config = "list = [1, 2, 3]"
my.config = ${?LIST_VAR}

// code
String listString = ConfigFactory.load().getString("my.config")
ConfigFactory.parseString(listString).getIntList("list")

然后设置LIST_VAR='list = [4, 5, 6]' 以覆盖默认值。请注意,您需要list = ,因为对象是 hocon 顶层需要,不能使用数组。

- 或 -

如果您的数据足够干净,您可以在,s 上拆分:

// application.conf
my.config = "foo,bar,baz"
my.config = ${?CSV_VAR}

// java code
String csvString = ConfigFactory.load().getString("my.config")
String[] parameters = csvString.split(",")

然后,只需设置CSV_VAR=bing,bang,boom,pow(没有[])。

进一步阅读

另一方面,如果您为每个值使用单独的环境变量,则有多种选择。

无默认值

最简单的,如果你不需要默认值,看起来像这样:

my.config = [ ${?MY_ENV_VAR}, ${?MY_ENV_VAR_TWO} ]

省略任何未定义的值。

添加到默认值

如果你只需要添加默认值,你可以使用+=syntax

my.config = [1, 2]
my.config += ${?MY_ENV_VAR}
my.config += ${?MY_ENV_VAR_TWO}

任何未定义的值都不会添加到数组中。

最大的灵活性

我发现最灵活的选项是在您的application.conf(或reference.conf-D 选项或您提供配置的任何其他位置)中使用positional syntax

my.config.0 = 1                    // always set to 1  
my.config.1 = 2                    // defaults to 2 if MY_ENV_VAR is not set
my.config.1 = ${?MY_ENV_VAR}
my.config.2 = ${?MY_ENV_VAR_TWO}   // totally optional
my.config.3 = ${MY_ENV_VAR_THREE}  // doesn't have ?, so it is required

任何已定义的值都将被包括在内,任何未定义的值都将被跳过。例如,如果MY_ENV_VAR=4MY_ENV_VAR_THREE=6MY_ENV_VAR_TWO 未设置,结果列表将为 [1, 4, 6]

对象列表

您甚至可以在列表中定义对象,如下所示:

my.nested.0.myField = 1
my.nested.0.otherField = "hello"
my.nested.1.myField = 2
my.nested.1.myField = ${?MY_INT}
my.nested.1.otherField = "goodbye"
my.nested.1.otherField = ${?MY_STRING}
my.nested.2.myField = ${OTHER_INT}       // Note lack of ?
my.nested.2.otherField = ${OTHER_STRING} // Note lack of ?

至少在我的测试中,配置对象列表的一个问题是所有项目都需要完全定义。因此 没有默认值的字段是必需的替换。如果MY_INT=99MY_STRING没有设置,OTHER_INT=100, 和OTHER_STRING=foo,以上呈现为:

other {
  nested = [
    { myField = 1, otherField = "hello" },
    { myField = 99, otherField = "goodbye" },
    { myField = 100, otherField = "foo" }
  ]
}

【讨论】:

  • 酷调查!谢谢!没想到HOCON这么强大
【解决方案2】:

不,这是不可能的。

来自 Hocon docs:

环境变量总是变成一个字符串值,但是如果一个应用程序要求另一种类型,自动类型转换就会启动

来自同一文档的关于自动类型转换的注释:

不应执行以下类型转换:

...

任何东西到数组,除了数字索引的对象到数组

将对象和数组与字符串相互转换很诱人,但在实际情况下会引发引用和双重转义的棘手问题。

【讨论】:

    猜你喜欢
    • 2016-12-13
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    相关资源
    最近更新 更多