3

我使用的是 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 替换的正确方法是什么?提前致谢。

4

2 回答 2

6

答案

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

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

// 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} ]

任何未定义的值都将被忽略。

添加到默认值

如果您只需要添加到默认值,您可以使用+= 语法

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

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

最大的灵活性

我发现的最灵活的选项是在您的(或或选项或您提供配置的其他任何地方)中使用位置语法:application.confreference.conf-D

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=99,MY_STRING未设置, OTHER_INT=100, 和OTHER_STRING=foo, 则上述呈现为:

other {
  nested = [
    { myField = 1, otherField = "hello" },
    { myField = 99, otherField = "goodbye" },
    { myField = 100, otherField = "foo" }
  ]
}
于 2020-12-22T22:53:37.400 回答
1

不,那是不可能的。

来自 Hocon文档

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

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

不应执行以下类型转换:

...

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

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

于 2020-05-06T10:11:32.320 回答