作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这就是我的意图 - 假设我有一个名为 medical_payments
的字段 - 它可以“要么”是一个限制,如果有人选择或放弃
{
"medical_payments":
{
"limit_value":"one_hundred"
}
}
如果它被选为豁免,那么它应该是:
{
"medical_payments":
{
"waived":true
}
}
到目前为止,这是我所拥有的:
sealed trait LimitOrWaiver
case class Limit(limit_key: String) extends LimitOrWaiver
case class Waived(waived: Boolean) extends LimitOrWaiver
case class Selection(medical_payments: LimitOrWaiver)
示例数据:
Selection(medical_payments = Limit("one_hundred")).asJson
输出:
{
"medical_payments":
{
"Limit": { "limit_value":"one_hundred" } // additional object added
}
}
与 Selection(medical_payments = Waived(true)).asJson
类似,将额外的 Waived:{...}
添加到 Json。
我希望它是非此即彼。实现这一目标的最佳方法是什么?
我能想到的(不是我喜欢的)唯一方法是使用forProductN
函数per the doc并手动完成所有这些 - 但对于大型 Json 来说,这是一种麻烦的方式。
最佳答案
您几乎可以使用 generic-extras 中的配置通过泛型派生来完成此操作:
sealed trait LimitOrWaiver
case class Limit(limitValue: String) extends LimitOrWaiver
case class Waived(waived: Boolean) extends LimitOrWaiver
case class Selection(medicalPayments: LimitOrWaiver)
import io.circe.generic.extras.Configuration, io.circe.generic.extras.auto._
import io.circe.syntax._
implicit val codecConfiguration: Configuration =
Configuration.default.withDiscriminator("type").withSnakeCaseMemberNames
然后:
scala> Selection(medicalPayments = Limit("one_hundred")).asJson
res0: io.circe.Json =
{
"medical_payments" : {
"limit_value" : "one_hundred",
"type" : "Limit"
}
}
(请注意,我还将 Scala 案例类成员名称更改为 Scala 惯用的驼峰案例,并在配置中处理到蛇案例的转换。)
这不是您想要的,因为有额外的 type
成员,但是 circe 的泛型推导只支持可往返的编码器/解码器,并且没有某种鉴别器——要么像这样的成员或您在问题中指出的额外对象层——不可能通过 JSON 往返任意 ADT 的值。
这可能没问题——您可能不关心对象中额外的 type
。如果您愿意,您仍然可以通过一些额外的工作来使用推导:
import io.circe.generic.extras.Configuration, io.circe.generic.extras.auto._
import io.circe.generic.extras.semiauto._
import io.circe.ObjectEncoder, io.circe.syntax._
implicit val codecConfiguration: Configuration =
Configuration.default.withDiscriminator("type").withSnakeCaseMemberNames
implicit val encodeLimitOrWaiver: ObjectEncoder[LimitOrWaiver] =
deriveEncoder[LimitOrWaiver].mapJsonObject(_.remove("type"))
和:
scala> Selection(medicalPayments = Limit("one_hundred")).asJson
res0: io.circe.Json =
{
"medical_payments" : {
"limit_value" : "one_hundred"
}
}
如果您真的想要,您甚至可以将其设为自动,这样 type
就会从您派生的任何 ADT 编码器中删除。
关于scala - 如何让 circe 为生成的 Json 提供非此即彼的输出方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55961842/
我是一名优秀的程序员,十分优秀!