Вы можете сделать это довольно просто, сопоставив фильтр с выходом кодировщика (который может быть получен, определен с помощью 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. Это одна из причин, по которой я думаю, что в целом лучше всего возложить ответственность за сохранение нулевых значений исключительно на принтер, но в таком случае наличие или отсутствие пустых полей явно имеет семантическое значение, поэтому вы нужно перепутать уровни.
person
Travis Brown
schedule
19.03.2019