restangular: Undefined attributes are dropped when saving (POST, PUT)

Let’s say I want to save this object:

{
  foo: 1,
  bar: "...",
  baz: undefined
}

I would expect this to get sent:

{ "foo": 1, "bar": "...", "baz": null }

Instead what gets sent is:

{ "foo": 1, "bar": "..." }

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 2
  • Comments: 32 (12 by maintainers)

Most upvoted comments

Explanation:

JSON.stringify() converts a value to JSON notation representing it:

  • Properties of non-array objects are not guaranteed to be stringified in any particular order. Do not rely on ordering of properties within the same object within the stringification.
  • Boolean, Number, and String objects are converted to the corresponding primitive values during stringification, in accord with the traditional conversion semantics.
  • If undefined, a function, or a symbol is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array).
  • All symbol-keyed properties will be completely ignored, even when using the replacer function.

According to JSON spec, only null values are valid to be present in JSON document, so in order to preserve them, make sure you covert them to nulls before actually passing to Restangular. This can be easily achieved in request interceptors.

As this is not always the desired behaviour, I am not sure if this should be treated as a bug/feature to implement. For example - if user executes PATCH request, he expects to send only properties that has been set by the user. Otherwise - all undefined properties will be converted to nulls and may overwrite accidentally valid properties on the server side.

Normally, I think it’s a servers job to ensure that if value is not passed in the payload of POST method, it should be nullified automatically (with Hapi.js this is pretty easy when you do Joi.number().optional().default(0)).

Chances are really good you copied the object with something like angular.copy. Don’t do that (for now at least). The object is connected to the methods with bind() and when that happens, well, the original element that was bound to the function/method becomes the this inside the function.

As far as I know, there has been no fix for this.