undefined or null?

10,633 views
Skip to first unread message

Andrei Neculau

unread,
Mar 19, 2013, 12:08:39 PM3/19/13
to api-...@googlegroups.com


This may come as a stupidity, or as a troll, but it's not.
Has anyone given a good thought on what an API wins by providing strict structures (and return null or similar for undefined properties), or by providing dynamic structured (and just not return undefined properties) ?

From a pure API perspective (~forget consumption languages), the latter comes as a win imho
1 - keep the noise down - imagine 1 property set and 99 set to null
2 - keep it fair between client and server - as a client you wouldn't be happy if you had to POST a strict structure just to update 1 property out of 100, would you?
3 - implicit forward compatibility when removing properties
4 - easy checks - e.g. does the obj.subobj exists vs does obj.subobj have any non-null properties?
5 - some might say bandwidth, but come on..

But then there is the client perspective, and its "convenience", where obj.subobj.x can throw an error because subobj is undefined, while it would work if it was null. And now imagine that you would have to do that no matter the nesting depth.

"Solutions" for the former direction, from the client's perspective, would be things like - use a user-friendly language (e.g. coffeescript), or use a getter-like function get(from_obj, pointer, otherwise_default_to) or pre-process the obj (e.g. check once if obj.subobj is defined, if not defined assign it the null value).

My mind is set/stubborn, but I'd like to hear your views on this nit-pick.
Thanks

Peter Monks

unread,
Mar 19, 2013, 12:21:10 PM3/19/13
to api-...@googlegroups.com
G'day Andrei,

I'm fully behind the "dynamic structure" approach - having 3 different ways to represent "lack of value" (null, empty string/array/object, property elision) is redundant, and of those three elision is the most general (for all the reasons you describe) and so it's the approach we're using exclusively.  I've received some push back on this, but when pressed no one has yet come up with a compelling use case where there is a semantic difference between these three representations.

I'm keen to hear what the other members of this list have to say!

Cheers,
Peter


 
 


--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Phil Jackson

unread,
Mar 19, 2013, 4:49:54 PM3/19/13
to api-...@googlegroups.com
Hey Peter,

Personally I've no strong opinion on omitting a property instead of
representing it as null (though I suppose it depends on the data behind
it).

However, an empty array/object/string isn't a lack of value it's an
explicitly empty thing. For a start in many languages [], {}, "" aren't
falsey where as always null is. Secondly, in the case of omitting values
I would have to take an extra step to see if it's there, given:

"forSale": {
"ferrai": [ "F40", "F50" ],
"lamborghini": [],
}

In coffee script I can just loop the models:

for lambo_model in forSale.lamborghini
console.log lambo_model

Given null:

"forSale": {
"ferrai": [ "F40", "F50" ],
"lamborghini": null,
}

if forSale.lamborghini
for lambo_model in forSale.lamborghini
console.log lambo_model

Given omission:

"forSale": {
"ferrai": [ "F40", "F50" ]
}

# note the question mark
if forSale.lamborghini?
for lambo_model in forSale.lamborghini
console.log lambo_model

Data-wise, does the lack of a lamborghini mean the trading company never
deals in them? Or they do deal in them but just don't have any in stock?

So, semantically, they're different enough to represent using the
containers, IMO.

Cheers,
Phil
--
Apiaxle http://apiaxle.com - A free, open proxy for your API.

CJunge

unread,
Mar 19, 2013, 5:44:38 PM3/19/13
to api-...@googlegroups.com
At my work we chose null to indicate the existence of a property, which has no value.

We chose that, as a partial embedded resource may have a property set to null, to indicate that it's MEANT to be null, and not just omitted.

It's possibly a bit clumsy, but saves on more API calls to get a full resource when the property required is empty.

Cheers, Cameron

Andrei Neculau

unread,
Mar 22, 2013, 6:49:25 AM3/22/13
to api-...@googlegroups.com
Thanks Phil

To stick to the topic: undefined or null, rather than undefined/null/[]/{}/""/0, you have to take that step back even with null. Am I missing something?

Regarding the non-undefined, non-null options.. you are right. One is undefined, one is defined (and has a type) but empty. There is semantic difference. It doesn't work like that for integers and more obviously for booleans. An array, an object, a string can be empty, but not an integer or boolean. What happens next is that you assign semantics to values e.g. let's just assume that -1 means undefined. That's a big failure, because next you have a signed int property, and then you will say.. ahh, but let's say -MAXINT is undefined, etc.
So there is semantic difference, but how does that reflect into a decisional factor? "if X is undefined then ...; else if isArray and X.length is 0 then ...; else ..." ?!

The question you raise is a false path IMHO. Your question is just highlighting that "forSale" may have a fluffy definition, because the name is seriously fluffy "stuff forSale".
Is it defined as "brands and models up for sale" or "models up for sale"? To me it's clear that the latter is a better choice, along the lines of single responsibility. Otherwise, you're telling me that I have to consume the whole list of cars, in order to see what brands are up for sale. Of course you can go different paths as well -- carsForSale: [{..}, {..}] but that's out of this thread's scope.


Andrei Neculau

unread,
Mar 22, 2013, 8:19:21 AM3/22/13
to api-...@googlegroups.com
Let me see if I get this right, Cameron

if a "car" has "owner" = null, then it means it has no owner
if a "car" has "owner" undefined, then it means it was omitted, and that the client could make an additional request to the "owner" resource, and fetch data

If that's correct, that's interesting, but not very clean IMHO. I'm stating upfront I have no goal in trying to change your mind, or saying this is wrong though. As many others on this forum say at times - it's not right or wrong, it just a decision to go left or right. So take "not very clean" as "I wouldn't have though of that" :) But I don't understand why not clearly defining if "car" will return an "owner" (if it has one), or saying that the "owner" will always have to be fetched. 

Cameron Junge

unread,
Mar 22, 2013, 4:18:26 PM3/22/13
to api-...@googlegroups.com

We chose that to give us the flexibility to include parts of a resource or not, depending on usage.

If a car has a owner but the general usage is to use the owner name and phone number then we can reduce data by including a link to the owner resource but also include the owner name and phone number in the embedded resource. If the car owner doesn't have an phone number, using null tells the client app that there's no point following a link if they want the owner's phone number as its explicitly null and not just omitted.

May not be good solution but it works for us.

--
You received this message because you are subscribed to a topic in the Google Groups "API Craft" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/api-craft/MrEixUwOCWA/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to api-craft+...@googlegroups.com.

b tork

unread,
Apr 12, 2018, 12:56:46 PM4/12/18
to API Craft
My experience has been to use undefined to mean "no change to the value" and null to specifically set the value to null. As mentioned in another response, non-nullable values need to be treated special. We chose to return an error if a non-nullable value was attempted to be set to null. It could be omitted which would leave the value unchanged. The big advantage to this is that the client does not have to know all the values when setting an object. This is a concern when an object is heavily modified and a read-and-update could potentially have stale data. An example would be a jira ticket. Many people may be updating attributes of the ticket. If all you want to do is update the status then you don't want to have to read everything about the ticket and send it back and hope that it isn't updated in the meantime.

Reply all
Reply to author
Forward
0 new messages