Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent $.ajax from adding [] to my key names (without processData: false)?

Tags:

jquery

ajax

If I try to use $.ajax to POST a data dictionary like:

{
    list: ["fake_id_0"],
    mapType: "fakeToRealId"
}

jQuery does something strange to it; it transforms the data into:

{
    list[]: ["fake_id_0"],
    mapType: "fakeToRealId"
}

As you can see, it adds brackets to the list key, but not the mapType key. Now in a general REST sense, yes it is common for people to name keys with array values with brackets ... but my server doesn't work that way, so if I try to POST list[] I have problems.

I have tracked this problem down to $.ajax's handling of the parseData option, in this bit of code:

// Convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" ) {
    s.data = jQuery.param( s.data, s.traditional );
}

and if I use processData: false it does skip that block ... but then it also doesn't URLEncode my data for me.

So, my question is: how do make $.ajax calls with processData: true without having jQuery modify my key names on me? Or failing that, how do I use processData: false, but still get every effect from that option except the bracket-adding?

P.S. Or, if this is all non-standard jQuery behavior, being caused by some plug-in I have, please let me know that instead :-)

* EDIT *

I answered my own question, then deleted that answer because I realized that it was flawed. I answered that setting the option traditional:true (in the $.ajax call) fixes the brackets, and it does ... but it also has a side effect, which is that it will not serialize nested objects.

So my revised question is: how do make $.ajax calls with processData: true without having jQuery modify my key names on me AND without disabling its serialization of nested properties? In other words, how do I have jQuery do everything the same as it currently does ... except not add brackets to my keys?

like image 752
machineghost Avatar asked May 31 '13 22:05

machineghost


2 Answers

As you realized this is not a bug. The brackets were put there specifically to solve problems with multi-level objects, after version 1.4 I believe. You can have a look to .param() itself to understand why. http://api.jquery.com/jQuery.param/

I believe what you want is not possible and good way to verify is to try end encode one string by hand. I believe you will not be able to encode it in way that is uniquely decodable, without the brackets.

To amend my answer, quoting from the above link

Note: Because some frameworks have limited ability to parse serialized arrays, developers should exercise caution when passing an obj argument that contains objects or arrays nested within another array.

Note: Because there is no universally agreed-upon specification for param strings, it is not possible to encode complex data structures using this method in a manner that works ideally across all languages supporting such input. Use JSON format as an alternative for encoding complex data instead.

So if you server is ready to parse json, you can then send your request like this.

$.ajax({
    url: 'something',
    type: 'GET',
    data: JSON.stringify(data),
    contentType: 'application/json; charset=utf-8',
});
like image 145
alianos- Avatar answered Nov 16 '22 19:11

alianos-


I know it's already implied by the question body, but here's how you avoid this wonderful feature of jQuery's. If you have:

$.get(api_url, {my_param: my_arguments})

change it to:

$.get(api_url, $.param({my_param: my_arguments}, true))
like image 41
badp Avatar answered Nov 16 '22 19:11

badp