Outputting 'null' for Option[T] in play-json serialization when value is None Outputting 'null' for Option[T] in play-json serialization when value is None json json

Outputting 'null' for Option[T] in play-json serialization when value is None


The Json.writes macro generates a writeNullable[T] for optional fields. Like you know (or not), writeNullable[T] omits the field if the value is None, whereas write[Option[T]] generates a null field.

Defining a custom writer is the only option you have to get this behavior.

(   (__ \ 'name).write[String] and  (__ \ 'address).write[Option[String]])(unlift(Person.unapply _))


You can use a custom implicit JsonConfiguration, see Customize the macro to output null

implicit val config = JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)implicit val personWrites = Json.writes[Person]    Json.toJson(Person("John Smith", None))


Not a real solution for you situation. But slightly better than having to manually write the writes

I created a helper class that can "ensure" fields.

implicit class WritesOps[A](val self: Writes[A]) extends AnyVal {    def ensureField(fieldName: String, path: JsPath = __, value: JsValue = JsNull): Writes[A] = {      val update = path.json.update(        __.read[JsObject].map( o => if(o.keys.contains(fieldName)) o else o ++ Json.obj(fieldName -> value))      )      self.transform(js => js.validate(update) match {        case JsSuccess(v,_) => v        case err: JsError => throw new JsResultException(err.errors)      })    }    def ensureFields(fieldNames: String*)(value: JsValue = JsNull, path: JsPath = __): Writes[A] =      fieldNames.foldLeft(self)((w, fn) => w.ensureField(fn, path, value))}

so that you can write

Json.writes[Person].ensureFields("address")()