每次我想向Rails发布一个带有jQuery的JSON对象数组时,都会遇到这个问题。如果我对数组进行字符串化,我可以看到jQuery正在正确地工作:
"shared_items"=>"[{\"entity_id\":\"253\",\"position\":1},{\"entity_id\":\"823\",\"position\":2}]"
但是如果我只是将它作为AJAX调用的数据发送给数组,我会得到:
"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}
然而,如果我只发送一个普通数组,它就可以工作:
"shared_items"=>["entity_253"]
为什么Rails要将数组更改为这种奇怪的散列?我想到的唯一原因是Rails不能正确理解内容,因为这里没有类型(有没有办法在jQuery调用中设置它?):
Processing by SharedListsController#create as
谢谢!
更新:我将数据作为数组发送,而不是字符串,并且该数组是使用.push()
函数动态创建的。尝试使用$.post
和$.ajax
,结果相同。
发布于 2012-07-28 10:11:42
如果有人偶然发现了这一点并想要更好的解决方案,您可以在.ajax调用中指定“JSON:'application/json'”选项,让Rails正确地解析contentType对象,而不会将其混淆为具有全字符串值的整数键哈希。
所以,总结一下,我的问题是:
$.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}]}
});
导致Rails将内容解析为:
Parameters: {"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}}
鉴于此(注意:我们现在对javascript对象进行了字符串化并指定了一个内容类型,因此rails将知道如何解析我们的字符串):
$.ajax({
type : "POST",
url : 'http://localhost:3001/plugin/bulk_import/',
dataType: 'json',
contentType: 'application/json',
data : JSON.stringify({"shared_items": [{"entity_id":"253","position":1}, {"entity_id":"823","position":2}]})
});
在Rails中生成一个很好的对象:
Parameters: {"shared_items"=>[{"entity_id"=>"253", "position"=>1}, {"entity_id"=>"823", "position"=>2}]}
这在Ruby 1.9.3上的Rails3中适用。
发布于 2011-08-11 06:20:31
这个问题有点老生常谈,但今天我自己也遇到了这个问题,下面是我想出的答案:我认为这是jQuery的错,但它只是顺其自然。然而,我确实有一个变通的办法。
给定以下jQuery ajax调用:
$.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}]}
});
jQuery将发布的值将如下所示(如果您查看您的Firebug-of-choice中的请求)将为您提供如下形式的数据:
shared_items%5B0%5D%5Bentity_id%5D:1
shared_items%5B0%5D%5Bposition%5D:1
如果你用CGI.unencode搜索,你会得到
shared_items[0][entity_id]:1
shared_items[0][position]:1
我相信这是因为jQuery认为JSON中的那些键是表单元素名称,它应该将它们视为您有一个名为"username“的字段。
所以它们进入你的Rails应用程序,Rails看到括号,并构造一个散列来保存字段名的最里面的键( jQuery“有帮助地”添加的"1“)。
无论如何,我通过如下方式构造我的ajax调用来绕过这个行为;
$.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}])},
}
});
这迫使jQuery认为这个JSON是您想要完全传递的值,而不是它必须接受的Javascript对象,并将所有键转换为表单字段名称。
然而,这意味着Rails方面的情况有所不同,因为您需要显式地解码params:data中的JSON。
但这也没关系:
ActiveSupport::JSON.decode( params[:data] )
TL;DR:所以,解决方案是:在你的jQuery.ajax()调用的数据参数中,显式地执行{"data": JSON.stringify(my_object) }
,而不是将JSON数组输入到jQuery (它会错误地猜测你想要用它做什么。
发布于 2014-08-25 10:22:34
我刚刚在Rails 4中遇到了这个问题。要明确回答您的问题(“为什么Rails要将数组更改为这种奇怪的散列?”),请参阅Rails guide on Action Controllers的4.1节
若要发送一组值,请将一对空的方括号"[]“附加到键名。
问题是,jQuery使用显式数组索引来格式化请求,而不是使用空方括号。因此,例如,它发送shared_items[0]=1&shared_items[1]=2
而不是发送shared_items[]=1&shared_items[]=2
。Rails查看数组索引并将其解释为散列键而不是数组索引,从而将请求转换为奇怪的Ruby散列:{ shared_items: { '0' => '1', '1' => '2' } }
。
如果您无法控制客户端,可以通过将散列转换为数组在服务器端修复此问题。下面是我是如何做到的:
shared_items = []
params[:shared_items].each { |k, v|
shared_items << v
}
https://stackoverflow.com/questions/6410810
复制相似问题