Circe:将可选字段强制为“ null”

时间:2019-03-18 20:16:51

标签: scala circe

有没有一种方法可以将单个None字段序列化为“ null”?

例如:

// When None, I'd like to serialize only f2 to `null`
case class Example(f1: Option[Int], f2: Option[Int])
val printer = Printer.noSpaces.copy(dropNullValues = true)

Example(None, None).asJson.pretty(printer) === """{"f2":null}"""

1 个答案:

答案 0 :(得分:2)

您可以通过在编码器的输出(可以派生,用Encoder.forProductN等定义的编码器)上映射过滤器来直接完成此操作:

import io.circe.{ Json, ObjectEncoder }
import io.circe.generic.semiauto.deriveEncoder

case class Example(f1: Option[Int], f2: Option[Int])

val keepSomeNulls: ((String, Json)) => Boolean = {
  case ("f1", v) => !v.isNull
  case (_, _) => true
}

implicit val encodeExample: ObjectEncoder[Example] =
  deriveEncoder[Example].mapJsonObject(_.filter(keepSomeNulls))

然后:

scala> import io.circe.syntax._
import io.circe.syntax._

scala> Example(Some(1), Some(2)).asJson.noSpaces
res0: String = {"f1":1,"f2":2}

scala> Example(Some(1), None).asJson.noSpaces
res1: String = {"f1":1,"f2":null}

scala> Example(None, Some(2)).asJson.noSpaces
res2: String = {"f2":2}

scala> Example(None, None).asJson.noSpaces
res3: String = {"f2":null}

请注意,配置打印机以丢弃空值仍会在此处删除"f2": null。这是我认为一般最好将空值的保留完全由打印机负责的部分原因,但是在这种情况下,存在或不存在空值字段显然在语义上是有意义的,因此您可以必须混合级别。