Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicitly output JSON null in case of missing optional value

Consider this example using Play's 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 is None, the resulting JSON won't have location field at all. This is fine and understadable. But if I wanted for some reason (say, to make my API more self-documenting), how can I explicitly output null in JSON?

{      
  "location": null
}

I also tried defining the field as location: LocationJson and passing option.orNull to it, but it does not work (scala.MatchError: null at play.api.libs.json.OWrites$$anon$2.writes). For non-custom types such as String or Double, this approach would produce null in JSON output.

So, while using Json.writes[FooJson] as shown above (or something equally simple, i.e. not having to write a custom Writes implementation), is there a clean way to include nulls in JSON?

What I'm asking is analogous to JsonInclude.Include.ALWAYS in the Jackson library (also Jackson's default behaviour). Similarly in Gson this would be trivial
(new GsonBuilder().serializeNulls().create()).

Play 2.4.4

like image 642
Jonik Avatar asked Dec 16 '15 16:12

Jonik


People also ask

How to include null values in the for JSON clause?

APPLIES TO: SQL Server Azure SQL Database Azure SQL Data Warehouse Parallel Data Warehouse. To include null values in the JSON output of the FOR JSON clause, specify the INCLUDE_NULL_VALUES option. If you don't specify the INCLUDE_NULL_VALUES option, the JSON output doesn't include properties for values that are null in the query results.

When serializing to JSON what happens to NULL values?

When serializing to JSON, if a value of a property in the data object is null, then it will be serialized as a JSON null. Non-existence of a property from the JSON data maps to an unset attribute in the data object space. If the property in the data object is not set (unset), then the property will not appear in the JSON data.

Why does parse JSON return a null error?

The Parse JSON step with the above schema returns "Error - Expected String, received null" Replacing the EndDate data type "string" with "any" causes it to be unreadable in following steps (as though it was never parsed) and changing it to "data" causes an internal server error.

How do I ignore a JSON property in a request?

[ JsonProperty ( "id", DefaultValueHandling = DefaultValueHandling. Ignore )] private EndpointId _id; This allows users to omit the JSON property in a request to the server. However, in some cases it's important to be able to explicitly send a property with a null value (e.g. #420 ).


1 Answers

Greg Methvin, a Play committer, wrote this answer to me in a related GitHub issue:

The JSON macros only support one way of encoding optional values, which is to omit None values from the JSON. This is not a bug but rather a limitation of the implementation. If you want to include nulls you're unfortunately going to have to implement your own Writes.

I do think we should try to provide more configurability for the macros though.

In this case, I'll let Play exclude this field when the value is null, even if it slightly sacrifices API consistency and self-documentability. It's still such a minor thing (in this particular API) that it doesn't warrant uglifying the code as much as a custom Writes would take for a case class with a dozen values.

I'm hoping they do make this more configurable in future Play versions.

like image 69
Jonik Avatar answered Sep 29 '22 15:09

Jonik