gpt4 book ai didi

scala - 如何使用 Circe 创建选项类型的自定义编码?

转载 作者:行者123 更新时间:2023-12-02 04:17:47 27 4
gpt4 key购买 nike

可以有一个如下所示的类:

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
}

如何实现这种细粒度的控制?我尝试了 forProduct2mapJsonObject 的各种技巧,但无法让它正常工作:

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) 情况。

最佳答案

如果有{"waived": true}是任何 Option[Amount] 的预期行为如果它是 None,那么如果您为 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] 定义了另一个隐式编码器在最接近的范围(数据对象伴侣)中,它不会在全局范围中寻找隐式编码器,从而为您提供所需的信息。

关于scala - 如何使用 Circe 创建选项类型的自定义编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55978823/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com