Web API – Use Empty String, Null, or Remove Empty Property in API Requests/Responses

data typesweb-api

When transferring object through an API, as in schemaless JSON format, what is the ideal way to return non-existent string property? I know that there are different ways of doing this as in examples in the listed links below.

I'm sure I have used null in the past but don't have a good reason to give for doing that. It seems straight forward to use null when dealing with the database. But database seems like an implementation detail that shouldn't concern the party on the other side of the API. E.g. they probably use a schemaless datastore that only store properties with values (non-null).

From a code point of view, restricting string functions to work only with one type, i.e. string (not null), makes them easier to prove; avoiding null is also a reason for having Option object. So, if the code that produces request/response doesn't use null, my guess is the code on the other side of the API won't be forced to use null too.

I rather like the idea of using an empty string as an easy way to avoid using null. One argument that I heard for using null and against the empty string is that empty string means the property exists. Although I understand the difference, I also wonder if it's the just implementation detail and if using either null or empty string makes any real life difference. I also wonder if an empty string is analogous to an empty array.

So, which is the best way of doing it that addresses those concerns? Does it depend on the format of the object being transferred (schema/schemaless)?

Best Answer

TLDR; Remove null properties

The first thing to bear in mind is that applications at their edges are not object-oriented (nor functional if programming in that paradigm). The JSON that you receive is not an object and should not be treated as such. It's just structured data which may (or may not) convert into an object. In general, no incoming JSON should be trusted as a business object until it is validated as such. Just the fact that it deserialized does not make it valid. Since JSON also has limited primitives compared to back-end languages, it is often worth it to make a JSON-aligned DTO for the incoming data. Then use the DTO to construct a business object (or error trying) for running the API operation.

When you look at JSON as just a transmission format, it makes more sense to omit properties that are not set. It's less to send across the wire. If your back-end language does not use nulls by default, you could probably configure your deserializer to give an error. For example, my common setup for Newtonsoft.Json translates null/missing properties to/from F# option types only and will otherwise error. This gives a natural representation of which fields are optional (those with option type).

As always, generalizations only get you so far. There are probably cases where a default or null property fits better. But the key is not to look at data structures at the edge of your system as business objects. Business objects should carry business guarantees (e.g. name at least 3 characters) when successfully created. But data structures pulled off the wire have no real guarantees.

Related Topic