1

假设我有以下配置:

{
  “default-value”:5,
  “some-seq”: [
    {“some-other-value”:100},
    {“foo”:”bar”},
    {“some-other-value”:1500}
  ]
}

我希望它被解码为案例类:

case class Config(defaultValue: Int, someSeq: Seq[SomeInteger])
case class SomeInteger(someOtherValue: Int)

这样它就会创建 Config(5, Seq(SomeInteger(100), SomeInteger(5), SomeInteger(1500))) (第二个是 5,因为列表的第二个对象中没有其他值键)是有办法吗?

4

1 回答 1

2

您可以添加一个类型参数SomeIntegerConfig指定someOtherValue应该是什么类型。然后创建一个ConfigReader[Config[Option[Int]]]并使用该map方法应用默认值:

case class Config[A](defaultValue: Int, someSeq: Seq[SomeInteger[A]])
object Config {
  private def applyDefault(config: Config[Option[Int]]): Config[Int] =
    config.copy(
      someSeq = config.someSeq.map(i =>
        i.copy(
          someOtherValue = i.someOtherValue.getOrElse(config.defaultValue))))

  implicit val reader: ConfigReader[Config[Int]] =
    deriveReader[Config[Option[Int]]]
      .map(applyDefault)
}
case class SomeInteger[A](someOtherValue: A)
object SomeInteger {
  implicit val reader: ConfigReader[SomeInteger[Option[Int]]] =
    deriveReader[SomeInteger[Option[Int]]]
}

不幸的是,这意味着您需要在Config[Int]任何地方都写,而不仅仅是Config. 但这可以通过重命名Config为 egGenConfig并添加类型别名来轻松解决:type Config = GenConfig[Int]

于 2021-06-12T21:39:12.517 回答