-1

I have the following code:

$.ajax({
    method: "POST",
    url: "/handler",
    contentType: "application/json",
    data: data_all,
  })
.done(function(r) { ...stuff... })
.fail(function(r) { ...stuff... });

data_all is a dictionary (e.g., {"a":1, "b":2}). Running this code currently returns a 400 error (using django, in case relevant). If I make one change:

  ...
  data: JSON.stringify(data_all),
  ...

It all works.

The thing is, that shouldn't be the case. The jQuery AJAX docs clearly states that the data argument accepts strings, arrays, and PlainObjects. When in debugger mode (using Chrome dev tools), I have verified that data_all is a PlainObject:

jQuery.isPlainObject(data_all)  # returns "true"

I'm using jQuery 2.1.4, so this should be there. Any idea why this requires the stringify function?

eykanal
  • 26,437
  • 19
  • 82
  • 113
  • @Mikey - thanks, fixed – eykanal Mar 13 '17 at 21:28
  • Right, you can give it an object. But jQuery will not auto-convert said object to match your given content type. an Object is not json, jquery will convert that object to a param string, thus giving you invalid data for your content type. It's all in the docs. – Kevin B Mar 13 '17 at 21:33
  • Look at the Network tab in your browser's Developer tools and see what gets passed to the service in each case. You could also try setting `processData: false` in your ajax options object. – Heretic Monkey Mar 13 '17 at 21:35
  • processData: false while still using an object will not have the expected results. (i would expect it to result in the body containing `[object Object]`) – Kevin B Mar 13 '17 at 21:35
  • @KevinB - But stringify doesn't output json object either, it's a string representation of json data. There's something going on under the hood either way. (I think...) – eykanal Mar 13 '17 at 21:38
  • No, json.stringify outputs a string. jQuery will not modify strings, so it gets passed to the body directly. – Kevin B Mar 13 '17 at 21:38
  • Curious why the downvote as well, I tried to do my research on this and it doesn't seem obvious to me. – eykanal Mar 13 '17 at 21:39
  • Your title states that jquery isn't accepting a plain object as data, but it is accepting a plain object as data. It just isn't converting said object to the format your server expects. *It wasn't designed to do so*. – Kevin B Mar 13 '17 at 21:40
  • @KevinB - That just reflects my not understanding that there's a conversion required, it wasn't intended to be intentionally misleading. Ah well, to each his own. If you write your comment as an answer I'll accept it. – eykanal Mar 13 '17 at 21:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138015/discussion-between-eykanal-and-kevin-b). – eykanal Mar 14 '17 at 13:12

1 Answers1

1

To send json data with jquery, you must stringify the object before passing it to jQuery; jQuery will not do it for you.

Under the hood, If the processData parameter is true (it is by default) and the data parameter doesn't contain a string, the value of the data parameter is passed to $.param() which creates a param string. Therefore, if you pass an object to the data param, your request body will contain a=1&b=2. If you simply set processData to false, jquery will skip the $.param process and directly send the .toString value of your object to the request body, which is [object Object], so that's not going to work either. If you stringify the object to JSON, it will be a string and jQuery will pass it through unchanged to the request body.

Kevin B
  • 94,570
  • 16
  • 163
  • 180