scala - 将类型安全配置解析为案例类

标签 scala adt case-class typesafe-config

什么是适合解析的案例类:

input {
    foo {
      bar = "a"
      baz = "b"
    }

    bar {
      bar = "a"
      baz = "c"
      other= "foo"
    }
}

来自 https://github.com/kxbmap/configs 的类型安全 HOCON 配置?

如何通过 ADT 读取它?查看他们的示例,我不确定如何构建类层次结构,其中某些类具有不同数量的字段 - 但可以继承一些。

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 值;即只是 foobar),那么你可以这样做:

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)))

--

如果您打算设置通用输入的序列,那么您应该在配置中反射(reflect)这一点并解析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)))

关于scala - 将类型安全配置解析为案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47895660/

相关文章:

scala - 仅在满足条件时覆盖默认参数

scala - Trait 继承和 self 类型注释之间的区别

android - Eclipse android 模拟器卡住

scala - 如何在案例类同伴中覆盖 apply

android - 为什么 MediaPlayer 在创建它的实例时会抛出 NOT present 错误?

android - 卸载安卓 ADT

java - 在java中将json字符串解析为scala案例类

java - 关于性能和 Java 互操作性 : Clojure vs. Scala

scala - 向 Scala 添加自定义编译时检查

scala - 为什么在一种情况下而不是另一种情况下得到 “missing parameter for expanded function”?