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")()