代码之家  ›  专栏  ›  技术社区  ›  Georg Heiler

将Typesafe配置解析为case类

  •  3
  • Georg Heiler  · 技术社区  · 8 年前

    什么是配件 案例类别 要分析:

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

    从类型安全HOCON配置通过 https://github.com/kxbmap/configs ?

    如何通过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'
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Szymon Jednac    8 年前

    如果 input 配置将始终包括 2 字段(如示例所示 txt 价值i、 e.只是 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)))