在Ruby on Rails中将字符串解析为查询字符串

86

我有一个像这样的字符串:

"foo=bar&bar=foo&hello=hi"

Ruby on Rails提供了解析查询字符串的方法吗?这样我就可以获得像这样的哈希值:

{
    :foo => "bar",
    :bar => "foo",
    :hello => "hi"
}

还是要我自己写吗?

编辑

请注意,上面的字符串不是来自URL的真实查询字符串,而是来自Facebook Connect中存储在cookie中的字符串。

5个回答

176

答案取决于您使用的 Rails 版本。如果您使用的是 2.3 或更高版本,则应使用 Rack 内置的参数解析器。

 Rack::Utils.parse_nested_query("a=2") #=> {"a" => "2"}

如果你使用的是旧版本的Rails,你可以确实使用CGI::parse。请注意,处理哈希和数组在模块之间存在细微差别,因此您需要验证所选方法获取的数据是否正确。

您还可以将Rack::Utils包含到您的类中以进行简写访问。


如果你想要像Rails提供的那样获取一个params对象,你可以这样做: params = ActionController::Parameters.new(Rack::Utils.parse_nested_query("a=2")) - adailey
有人知道是否可以避免查询字符串参数值被强制转换为字符串吗?例如,我想要这种行为:Rack::Utils.raw_parse_nested_query("a=2") #=> {"a" => 2} - mecampbellsoup
1
尽管通常情况下这很好:它将"a[]=&a[]=z"解析为{"a[]"=>["", "z"]},但实际使用的任何解析器ActionController::Base返回{:a => ["z"]} - Jeremy List
文档:https://www.rubydoc.info/gems/rack/Rack%2FQueryParser:parse_nested_query - Ulysse BN

40

这个

CGI::parse("foo=bar&bar=foo&hello=hi")
提供给你。
{"foo"=>["bar"], "hello"=>["hi"], "bar"=>["foo"]}

编辑: 如Ryan Long所指定的,这个版本考虑了同一关键字有多个值的情况,如果您要解析数组,这是很有用的。

编辑2:

正如Ben指出的那样,当使用ruby on rails风格的数组表示方式时,它可能无法处理数组。rails风格的数组表示方式是:foo[]=bar&foo[]=nop。使用Julik's response才能正确处理那种格式。

如果您的参数像foo=bar&foo=nop一样,则此版本将仅正确解析数组。


2
这是我尝试过的唯一一个处理每个参数的多个实例的实现 - 谢谢! - Ryan Long
8
问题在于大多数人不想要数组,而是期望一个简单的键值对应的响应。 - Ben G
@julik 的答案应该被接受。CGI::parse 不能正确处理数组。 - Ben

15

编辑:如评论中所述,使用符号化键可以导致您的服务器崩溃,如果有人想伤害您。我在处理低调应用程序时仍然经常这样做,因为这使得工作更容易,但我不会再在高利润应用程序中这样做了。

不要忘记对键进行符号化以获取您想要的结果。

Rack::Utils.parse_nested_query("a=2&b=tralalala").deep_symbolize_keys

这个操作对于重复的元素是具有破坏性的。


8
将用户提供的密钥转换为符号是不好的做法。符号不会被垃圾回收,因此如果有人用大量虚假参数密钥向您的服务器发送垃圾邮件,则最终会耗尽进程内存。 - Julik
6
Ruby 2.2现在将回收符号。 - Lesleh

9
如果您谈论的是用于获取关于参数的数据的URL,请注意以下几点:
> request.url
=> "http://localhost:3000/restaurants/lokesh-dhaba?data=some&more=thisIsMore"

接下来我们来获取查询参数,使用:

> request.query_parameters
=> {"data"=>"some", "more"=>"thisIsMore"}

2
如果你需要使用哈希,你可以使用以下方式:
Hash[CGI::parse(x).map{|k,v| [k, v.first]}]

9
CGI.parse(query).transform_values(&:first) - chocolateboy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接