将类型安全配置解析为案例 class
Parsing Typesafe configuration to a case class
什么是适合案例class解析:
input {
foo {
bar = "a"
baz = "b"
}
bar {
bar = "a"
baz = "c"
other= "foo"
}
}
来自类型安全的 HOCON 配置,通过 https://github.com/kxbmap/configs?
如何通过 ADT 读取它?查看他们的示例,我不确定如何构建一个 class 层次结构,其中一些 class 具有不同数量的字段 - 但可以继承一些。
sealed trait Tree
case class Branch(value: Int, left: Tree, right: Tree) extends Tree
case object Leaf extends Tree
我这里的样本:
import at.tmobile.bigdata.utils.config.ConfigurationException
import com.typesafe.config.ConfigFactory
import configs.syntax._
val txt =
"""
|input {
| foo {
| bar = "a"
| baz = "b"
| type = "foo"
| }
|
| bar {
| bar = "a"
| baz = "c"
| other= "foo"
| type="bar"
| }
|}
""".stripMargin
val config = ConfigFactory.parseString(txt)
config
sealed trait Input{ def bar: String
def baz:String }
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar:String, baz:String, other:String)extends Input
config.extract[Input].toEither match {
case Right(s) => s
case Left(l) =>
throw new ConfigurationException(
s"Failed to start. There is a problem with the configuration: " +
s"${l.messages.foreach(println)}"
)
}
失败:
No configuration setting found for key 'type'
如果 input
配置将始终包含 2
字段(如示例中的 txt
值;即仅 foo
和 bar
),那么你可以这样做:
val txt =
"""
|input {
| foo {
| bar = "a"
| baz = "b"
| type = "foo"
| }
|
| bar {
| bar = "a"
| baz = "c"
| other = "foo"
| type = "bar"
| }
|}
""".stripMargin
sealed trait Input {
def bar: String
def baz: String
}
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar: String, baz: String, other:String) extends Input
case class Inputs(foo: Foo, bar: Bar)
val result = ConfigFactory.parseString(txt).get[Inputs]("input")
println(result)
输出:
Success(Inputs(Foo(a,b),Bar(a,c,foo)))
--
如果您打算设置一个 序列 通用输入,那么您应该在配置中反映这一点并解析 Seq[Input]
:
val txt =
"""
|inputs = [
| {
| type = "Foo"
| bar = "a"
| baz = "b"
| }
|
| {
| type = "Bar"
| bar = "a"
| baz = "c"
| other= "foo"
| }
|]
""".stripMargin
sealed trait Input {
def bar: String
def baz: String
}
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar: String, baz: String, other: String) extends Input
val result = ConfigFactory.parseString(txt).get[Seq[Input]]("inputs")
println(result)
输出:
Success(Vector(Foo(a,b), Bar(a,c,foo)))
什么是适合案例class解析:
input {
foo {
bar = "a"
baz = "b"
}
bar {
bar = "a"
baz = "c"
other= "foo"
}
}
来自类型安全的 HOCON 配置,通过 https://github.com/kxbmap/configs?
如何通过 ADT 读取它?查看他们的示例,我不确定如何构建一个 class 层次结构,其中一些 class 具有不同数量的字段 - 但可以继承一些。
sealed trait Tree case class Branch(value: Int, left: Tree, right: Tree) extends Tree case object Leaf extends Tree
我这里的样本:
import at.tmobile.bigdata.utils.config.ConfigurationException
import com.typesafe.config.ConfigFactory
import configs.syntax._
val txt =
"""
|input {
| foo {
| bar = "a"
| baz = "b"
| type = "foo"
| }
|
| bar {
| bar = "a"
| baz = "c"
| other= "foo"
| type="bar"
| }
|}
""".stripMargin
val config = ConfigFactory.parseString(txt)
config
sealed trait Input{ def bar: String
def baz:String }
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar:String, baz:String, other:String)extends Input
config.extract[Input].toEither match {
case Right(s) => s
case Left(l) =>
throw new ConfigurationException(
s"Failed to start. There is a problem with the configuration: " +
s"${l.messages.foreach(println)}"
)
}
失败:
No configuration setting found for key 'type'
如果 input
配置将始终包含 2
字段(如示例中的 txt
值;即仅 foo
和 bar
),那么你可以这样做:
val txt =
"""
|input {
| foo {
| bar = "a"
| baz = "b"
| type = "foo"
| }
|
| bar {
| bar = "a"
| baz = "c"
| other = "foo"
| type = "bar"
| }
|}
""".stripMargin
sealed trait Input {
def bar: String
def baz: String
}
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar: String, baz: String, other:String) extends Input
case class Inputs(foo: Foo, bar: Bar)
val result = ConfigFactory.parseString(txt).get[Inputs]("input")
println(result)
输出:
Success(Inputs(Foo(a,b),Bar(a,c,foo)))
--
如果您打算设置一个 序列 通用输入,那么您应该在配置中反映这一点并解析 Seq[Input]
:
val txt =
"""
|inputs = [
| {
| type = "Foo"
| bar = "a"
| baz = "b"
| }
|
| {
| type = "Bar"
| bar = "a"
| baz = "c"
| other= "foo"
| }
|]
""".stripMargin
sealed trait Input {
def bar: String
def baz: String
}
case class Foo(bar: String, baz: String) extends Input
case class Bar(bar: String, baz: String, other: String) extends Input
val result = ConfigFactory.parseString(txt).get[Seq[Input]]("inputs")
println(result)
输出:
Success(Vector(Foo(a,b), Bar(a,c,foo)))