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

时间:2015-02-18 01:40:18

标签: json scala argonaut

我正在处理我的直接控制之外的一些代码,我需要编码一个选项[Thing],如果Thing存在则情况按照正常情况进行编码,但是None情况必须返回'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. 对于无:

    "thing": false
    
  3. 但目前无案例给出:

    "thing":null
    

    如何让它返回false?有人能指出我正确的方向吗?

    干杯

1 个答案:

答案 0 :(得分:4)

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

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}
  }
}

BiggerThingthing时,如何在没有thing属性的情况下对None进行编码。您需要一个自定义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)
  }