angularjs 1.x: send {'key' : undefined} wi

2019-08-15 21:52发布

问题:

My requirement is that I want to be able to send an object like {title: "test", price: undefined} from my angular-app via $http.post to my nodejs app (to be able to delete the price key via Mongoose update in my mongoDB).

Problem:

Code extract

console.log(object)
$http.post(url, object)
  1. In the console, I see: {title: "test", price: undefined}
  2. My request payload contains {title: "test"}

==> Why doesn't my payload contain the full object? How can I add the price: undefined in my payload?

回答1:

When HTTP request Content-Type is application/json and the payload object contains undefined as some fields' value, those fields will be removed. Otherwise, server side program won't be able to parse the JSON successfully -- an error SyntaxError: Unexpected token u in JSON at position ... will happen (the token u is just the "u" of "undefined").

This is not an Angular specific behaviour, all HTTP requests should have this logic.


What happens in Angular's $http.post?

In Angular, all request data will be transformed. When the data is JSON, toJSON (which equals to angular.toJson) will be invoked to do the job (source code):

transformRequest: [function(d) {
  return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
}]

The toJson() function is just a proxy to JSON.stringify (source code):

function toJson(obj, pretty) {
  if (isUndefined(obj)) return undefined;
  if (!isNumber(pretty)) {
    pretty = pretty ? 2 : null;
  }
  return JSON.stringify(obj, toJsonReplacer, pretty);
}

In JSON.stringify:

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).



回答2:

It doesn't contain it because it is undefined. Undefined vars are removed from the request. You will just have to know, server-side that if the variable is not included, that you should delete it. Typically you want to use the PUT verb for updating a record, vs POST for creating a new record.

You could send an empty string or a boolean, or something special, so that you will know in your node app to delete the key.