0

I'm trying to use jquery.post to pass a parameter items with an Array as its value to the server. Like this:

HTML:

总共 <span class="statistics" data-fields="Record_entries_count"></span> 条记录,
总共 <span class"statistics" data-fields="drop_count"></span> 次。

Javascript:

this.items = this.element.find('span.statistics').toArray().map(i=>$(i).data('fields'));
$.post('backend_server', {"items": this.items}, function(data, status, xhr){...});

However, strangely enough it doesn't get passed correctly. I used the developer's tool to check the request header and found that what I passed as items becomes items[].

Why is this? Could someone please give a hint? Thanks a lot.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jinghui Niu
  • 990
  • 11
  • 28

1 Answers1

2

As this.items is an array, jQuery will introduce these brackets, as if you had done:

$.post('backend_server', {"items[]": this.items}, ....);

You can do it like that yourself, but jQuery will do this for you when you don't. See the examples in the jQuery documentation.

This is needed because the data structure that a post request supports is by nature flat. It follows the HTTP specification for "application/x-www-form-urlencoded", i.e. one or more parameter = value pairs in URL encoding. See this Q&A for several interesting answers on that format.

There is a consensus that parameter names with added square brackets denote that the original data is an array. So every array value will be encoded as a value of an items[] parameter.

Several server applications support this notation and will interpret it again as an array (e.g. PHP does this). If not, you'll have to take care of this at the server side.

Alternatives

If you want jQuery not to modify the names like that, you could change the jQuery settings for this with jQuery.ajaxSettings.traditional = true;.

Alternatively, you could stringify your object as JSON and send that string as one value:

$.post('backend_server', {"items": JSON.stringify(this.items) }, ....);

At the server side you'll then have to parse that JSON.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • thank you for your very detailed and rich answer. Just want to go one level further here while we are at it: why does it have to be 'flat'? Is it due to the fact that they are all transfered as strings? I just don't understand the purpose of such a conversion. By the way I'm using python as backend server and no it doesn't help you interpret so I will have to convert it back;) – Jinghui Niu Jul 11 '17 at 23:54
  • I elaborated a bit more on that in my answer and added a JSON alternative. – trincot Jul 12 '17 at 04:59
  • Thanks. Is there any potential drawbacks for always sticking with `jQuery.ajaxSettings.traditional = true;`? – Jinghui Niu Jul 12 '17 at 18:32
  • 1
    No, not that I know of. You just specify you don't want jQuery to be smart ;-) – trincot Jul 12 '17 at 18:33
  • Thank you trincot. Just one more question. why does jQuery.serializeArray() output is in the format of `[{name: 'foo1', value: 'bar1'}, {name: 'foo2', value: 'bar2'}]`, instead of a much simpler format as `{'foo1': 'bar1', 'foo2': 'bar2'}`? Also related to the http standard here? – Jinghui Niu Jul 12 '17 at 18:39
  • I asked the above question because my python server expects a dictionary as parameter, not an array. But magically somehow even though I throw array at it, it still works! – Jinghui Niu Jul 12 '17 at 18:45
  • jQuery uses that format as it is often used for form elements, where the name attributes of these form elements are not necessarily unique, and thus the simpler object notation is not possible. If you want a dictionary, I suppose the `JSON.stringify` solution, that I mentioned at the end of my answer, could be useful. In Python an array of pairs will transform easily to a dict, as is discussed [here](https://stackoverflow.com/questions/22614980/python-convert-pairs-list-to-dictionary) – trincot Jul 12 '17 at 20:08
  • Interesting. When the form elements are not unique, will the last one overwrite the previous one(s) when converted? – Jinghui Niu Jul 12 '17 at 20:54
  • If converted to a dict then indeed duplicate names will result in one key only, with the value of the last occurrence. – trincot Jul 13 '17 at 06:47