Assuming I have the following config:
{
“default-value”:5,
“some-seq”: [
{“some-other-value”:100},
{“foo”:”bar”},
{“some-other-value”:1500}
]
}
I want it to be decoded to case classes:
case class Config(defaultValue: Int, someSeq: Seq[SomeInteger])
case class SomeInteger(someOtherValue: Int)
So that it creates Config(5, Seq(SomeInteger(100), SomeInteger(5), SomeInteger(1500))) (Second one is 5 since there is no some-other-value key in the second object of the list) Is there a way to do so?
You can add a type parameter to SomeInteger
and Config
to specify what the type of someOtherValue
should be. Then you create a ConfigReader[Config[Option[Int]]]
and use the map
method to apply the default:
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]]]
}
Unfortunately this means you need to write Config[Int]
everywhere instead of just Config
. But this can easily be fixed by renaming Config
to e. g. GenConfig
and add a type alias: type Config = GenConfig[Int]
.