Scala argonaut 将 jEmtpyObject 编码为 'false' 而不是 'null'

Scala argonaut encode a jEmtpyObject to 'false' rather than 'null'

我正在处理一些我无法直接控制的代码,我需要在其中编码一个选项[Thing],如果 Thing 存在,则情况与正常情况一样,但是 None 情况必须 return 'false' 而不是 null。这能轻易完成吗?我正在查看文档,但没有取得太大成功。

我的代码如下所示:

   case class Thing(name: String)
   case class BiggerThing(stuff: String, thing: Option[Thing])

   implict val ThingEncodeJson: EncodeJson[Thing] =
     EncodeJson(t => ("name" := t.name ) ->: jEmptyObject)

和 BiggerThing 的等价物,json 需要看起来像:

  1. 对于一些:

    "thing":{"name": "bob"} 
    
  2. 对于 None:

    "thing": false
    

但目前 None 案例给出:

"thing":null

如何将其设置为 return false?有人能给我指出正确的方向吗?

干杯

您只需要 Option[Thing] 的自定义 CodecJson 实例:

object Example {
  import argonaut._, Argonaut._

  case class Thing(name: String)
  case class BiggerThing(stuff: String, thing: Option[Thing])

  implicit val encodeThingOption: CodecJson[Option[Thing]] =
    CodecJson(
      (thing: Option[Thing]) => thing.map(_.asJson).getOrElse(jFalse),
      json =>
        // Adopt the easy approach when parsing, that is, if there's no
        // `name` property, assume it was `false` and map it to a `None`.
        json.get[Thing]("name").map(Some(_)) ||| DecodeResult.ok(None)
    )

  implicit val encodeThing: CodecJson[Thing] =
    casecodec1(Thing.apply, Thing.unapply)("name")

  implicit val encodeBiggerThing: CodecJson[BiggerThing] =
    casecodec2(BiggerThing.apply, BiggerThing.unapply)("stuff", "thing")

  def main(args: Array[String]): Unit = {
    val a = BiggerThing("stuff", Some(Thing("name")))
    println(a.asJson.nospaces) // {"stuff":"stuff","thing":{"name":"name"}}
    val b = BiggerThing("stuff", None)
    println(b.asJson.nospaces) // {"stuff":"stuff","thing":false}
  }
}

thingNone 时,如何在没有 thing 属性 的情况下编码 BiggerThing。您需要一个自定义 EncodeJson[BiggerThing] 实例然后:

implicit val decodeBiggerThing: DecodeJson[BiggerThing] =
  jdecode2L(BiggerThing.apply)("stuff", "thing")

implicit val encodeBiggerThing: EncodeJson[BiggerThing] =
  EncodeJson { biggerThing =>
    val thing = biggerThing.thing.map(t => Json("thing" := t))
    ("stuff" := biggerThing.stuff) ->: thing.getOrElse(jEmptyObject)
  }