Explicitly display JSON null if an optional value is missing

Consider this example using the Play JSON API ( play.api.libs.json):

case class FooJson(
   // lots of other fields omitted
   location: Option[LocationJson]
)

object FooJson {
  implicit val writes = Json.writes[FooJson]
}

and

case class LocationJson(latitude: Double, longitude: Double)

object LocationJson {
  implicit val writes = Json.writes[LocationJson]
}

If location- None, as a result, JSON will not have a field at all location. This is beautiful and clear. But if I wanted for some reason (for example, to make my API more self-documenting) , how can I explicitly output nullto JSON ?

{      
  "location": null
}

I also tried to define the field as location: LocationJsonand pass it to him option.orNull, but it does not work ( scala.MatchError: nullat play.api.libs.json.OWrites$$anon$2.writes). For non-standard types, such as String or Double, this approach will result in NULL output in JSON output.

, Json.writes[FooJson], ( - , .. Writes), JSON ?

, , JsonInclude.Include.ALWAYS ( ). Gson  (new GsonBuilder().serializeNulls().create()).

2.4.4

+4
2

, Play, GitHub:

JSON , None JSON. , , . nulls, , Writes.

, .

Play , null, API . ( API), , Writes case .

, Play.

+3

:

object MyWrites extends DefaultWrites{

  override def OptionWrites[T](implicit fmt: Writes[T]): Writes[Option[T]] = new Writes[Option[T]] {
    override def writes(o: Option[T]): JsValue = {
      o match {
        case Some(a) => Json.toJson(a)(fmt)
        case None => JsNull
      }
    }
  }
}

, . :

case class FooJson(
                // ...
                location: Option[LocationJson]
              )

case class LocationJson(latitude: Double, longitude: Double)

object LocationJson {
  implicit val writes = Json.writes[LocationJson]
}

implicit val fooJsonWriter: Writes[FooJson] = new Writes[FooJson] {
  override def writes(o: FooJson): JsValue = {
    JsObject(Seq(
      "location" -> Json.toJson(o.location)
      // Additional fields go here.
    ))
  }
}

Json.toJson(FooJson(None))

res0: play.api.libs.json.JsValue = {"location":null}.

0

Source: https://habr.com/ru/post/1620386/


All Articles