可能有一个看起来像这样的类:
case class Amount(value: Int)
case class Data(insurance: Option[Amount], itemPrice: Amount)
如果insurance = None
应该获得默认值waived: true
例如:
Data(Some(123),100).asJson
// output
{
"insurance": {
"value": 123
},
"price": 100
}
And when no Insurance is opted for:
Data(None,100).asJson
// output
{
"insurance": {
"waived: true
},
"price": 100
}
如何实现这种细粒度的控制?我用forProduct2
和mapJsonObject
尝试了各种技巧,但无法使其正常运行:
implicit val testEncoder = deriveEncoder[Option[Amount]].mapJsonObject(j => {
val x = j("Some") match {
case Some(s) => // need to convert to [amount -> "value"]
case None => JsonObject.apply(("waived",Json.fromBoolean(true)))
}
x
})
这可以很容易地让我了解waived:true
部分,但不知道如何处理Some(s)
情况。
答案 0 :(得分:3)
如果对任何{"waived": true}
而言,如果预期它们都具有Option[Amount]
行为,那么如果您为Option[Amount]
编写自定义编码器,则可以依靠半自动派生编码器
这是一个例子
import io.circe.{Encoder, Json}
import io.circe.syntax._
import io.circe.generic.semiauto._
case class Amount(value: Int)
case class Data(insurance: Option[Amount], itemPrice: Amount)
object Amount {
implicit val encoder: Encoder[Amount] = deriveEncoder
}
object Data {
implicit val encoderOptionalAmount: Encoder[Option[Amount]] = (optA: Option[Amount]) =>
optA match {
case Some(amount) => amount.asJson
case None => Json.obj("waived" -> true.asJson)
}
implicit val encoder: Encoder[Data] = deriveEncoder[Data]
}
println(Data(insurance = None, itemPrice = Amount(10)).asJson)
/*
{
"insurance" : {
"waived" : true
},
"itemPrice" : {
"value" : 10
}
}
*/
工作原理:deriveEncoder[Data]
将为itemPrice(类型为Amount
)和类型为Option[Amount]
的保险调用隐式编码器。
Option[T]
的默认编码器只是跳过了None
的值,但是由于我们在最近的范围(数据对象伴随)中为Option[T]
定义了另一个隐式编码器,因此它看起来不会全局范围内的隐式编码器,可为您提供所需的确切信息。