A bit old question, but I fought it myself today, and here is the answer I came up with: I think this is a bit of a jQuery error, but that it only does what is natural to it. However, I have a workaround.
Given the following jQuery ajax call:
$.ajax({ type : "POST", url : 'http://localhost:3001/plugin/bulk_import/', dataType: 'json', data : {"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}]} });
The values ββthat jQuery publishes will look something like this (if you look at the query in your Firebug-of-choice), you will get form data that looks like this:
shared_items%5B0%5D%5Bentity_id%5D:1 shared_items%5B0%5D%5Bposition%5D:1
If you are CGI.unencode, you will receive
shared_items[0][entity_id]:1 shared_items[0][position]:1
I believe this is due to the fact that jQuery believes that these keys in your JSON are the names of the form elements and that they should treat them as if you had a field named "user [name]".
So, they enter your Rails application, Rails sees the brackets and builds a hash to store the very internal key of the field name ("1", which "jQuery" added ").
In any case, I circumvented this behavior by constructing my ajax call as follows:
$.ajax({ type : "POST", url : 'http://localhost:3001/plugin/bulk_import/', dataType: 'json', data : {"data": JSON.stringify({"shared_items": [{"entity_id":"253","position":1},{"entity_id":"823","position":2}])}, } });
Which makes jQuery think that this JSON is the value you want to pass in full, and not the Javascript object that it should accept, and turn all the keys into form field names.
However, this means that the Rails side is slightly different, because you need to explicitly decode JSON in the [: data] parameters.
But it normal:
ActiveSupport::JSON.decode( params[:data] )
TL; DR: So, the solution: in the data parameter for your jQuery.ajax () call, explicitly {"data": JSON.stringify(my_object) } , instead of {"data": JSON.stringify(my_object) } JSON array to jQuery (where it incorrectly assumes you want to do this.