Ruby:如何将哈希变成HTTP参数?
这很简单,像一个简单的散列
{:a => "a", :b => "b"} 这将转化为
 "a=a&b=b" 
但是,你如何处理更复杂的事情呢?
 {:a => "a", :b => ["c", "d", "e"]} 
应该翻译成
 "a=a&b[0]=c&b[1]=d&b[2]=e" 
更糟糕的是,(做什么)如下所示:
 {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}] 
感谢非常赞赏的帮助!
更新:此function已从gem中删除。
朱利安,你的自我回答是好的,我也是无耻借用的,但是它不能正确地逃避保留的字符,还有一些其他的边缘情况被破坏了。
 require "addressable/uri" uri = Addressable::URI.new uri.query_values = {:a => "a", :b => ["c", "d", "e"]} uri.query # => "a=a&b[0]=c&b[1]=d&b[2]=e" uri.query_values = {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]} uri.query # => "a=a&b[0][c]=c&b[0][d]=d&b[1][e]=e&b[1][f]=f" uri.query_values = {:a => "a", :b => {:c => "c", :d => "d"}} uri.query # => "a=a&b[c]=c&b[d]=d" uri.query_values = {:a => "a", :b => {:c => "c", :d => true}} uri.query # => "a=a&b[c]=c&b[d]" uri.query_values = {:a => "a", :b => {:c => "c", :d => true}, :e => []} uri.query # => "a=a&b[c]=c&b[d]" 
gem是“ 可寻址的 ”
 gem install addressable 
对于基本的非嵌套散列,Rails / ActiveSupport具有Object#to_query。
 >> {:a => "a", :b => ["c", "d", "e"]}.to_query => "a=a&b%5B%5D=c&b%5B%5D=d&b%5B%5D=e" >> CGI.unescape({:a => "a", :b => ["c", "d", "e"]}.to_query) => "a=a&b[]=c&b[]=d&b[]=e" 
http://api.rubyonrails.org/classes/Object.html#method-i-to_query
 如果您使用的是Ruby 1.9.2或更高版本,如果您不需要数组,则可以使用URI.encode_www_form 。 
例如(来自1.9.3中的Ruby文档):
 URI.encode_www_form([["q", "ruby"], ["lang", "en"]]) #=> "q=ruby&lang=en" URI.encode_www_form("q" => "ruby", "lang" => "en") #=> "q=ruby&lang=en" URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en") #=> "q=ruby&q=perl&lang=en" URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]]) #=> "q=ruby&q=perl&lang=en" 
 你会注意到数组值并没有用包含[]键名来设置,就像我们已经习惯的查询string一样。  encode_www_form使用的规范符合application/x-www-form-urlencoded数据的HTML5定义。 
如果您使用的是Rails,那么有更简单的方法: http : //apidock.com/rails/ActiveSupport/CoreExtensions/Hash/to_query
所以你可以这样做:
 {:a => "a", :b => "b"}.to_query 
 无需加载臃肿的ActiveSupport或自己动手,可以使用Rack::Utils.build_query和Rack::Utils.build_nested_query 。  这里有一个博客文章 ,提供了一个很好的例子: 
 require 'rack' Rack::Utils.build_query( authorization_token: "foo", access_level: "moderator", previous: "index" ) # => "authorization_token=foo&access_level=moderator&previous=index" 
它甚至可以处理数组:
 Rack::Utils.build_query( {:a => "a", :b => ["c", "d", "e"]} ) # => "a=a&b=c&b=d&b=e" Rack::Utils.parse_query _ # => {"a"=>"a", "b"=>["c", "d", "e"]} 
或者更困难的嵌套的东西:
 Rack::Utils.build_nested_query( {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}] } ) # => "a=a&b[][c]=c&b[][d]=d&b[][e]=e&b[][f]=f" Rack::Utils.parse_nested_query _ # => {"a"=>"a", "b"=>[{"c"=>"c", "d"=>"d", "e"=>"e", "f"=>"f"}]} 
从Merb偷窃:
 # File merb/core_ext/hash.rb, line 87 def to_params params = '' stack = [] each do |k, v| if v.is_a?(Hash) stack << [k,v] else params << "#{k}=#{v}&" end end stack.each do |parent, hash| hash.each do |k, v| if v.is_a?(Hash) stack << ["#{parent}[#{k}]", v] else params << "#{parent}[#{k}]=#{v}&" end end end params.chop! # trailing & params end 
请参阅http://noobkit.com/show/ruby/gems/development/merb/hash/to_params.html
如果您只需要支持简单的ASCII键/值查询string,下面是一个简短而又甜蜜的划线:
 hash = {"foo" => "bar", "fooz" => 123} # => {"foo"=>"bar", "fooz"=>123} query_string = hash.to_a.map { |x| "#{x[0]}=#{x[1]}" }.join("&") # => "foo=bar&fooz=123" 
 class Hash def to_params params = '' stack = [] each do |k, v| if v.is_a?(Hash) stack << [k,v] elsif v.is_a?(Array) stack << [k,Hash.from_array(v)] else params << "#{k}=#{v}&" end end stack.each do |parent, hash| hash.each do |k, v| if v.is_a?(Hash) stack << ["#{parent}[#{k}]", v] else params << "#{parent}[#{k}]=#{v}&" end end end params.chop! params end def self.from_array(array = []) h = Hash.new array.size.times do |t| h[t] = array[t] end h end end 
 {:a=>"a", :b=>"b", :c=>"c"}.map{ |x,v| "#{x}=#{v}" }.reduce{|x,v| "#{x}&#{v}" } "a=a&b=b&c=c" 
这是另一种方式。 对于简单的查询。
我知道这是一个古老的问题,但我只是想发布这些代码,因为我找不到一个简单的gem来完成这个任务。
 module QueryParams def self.encode(value, key = nil) case value when Hash then value.map { |k,v| encode(v, append_key(key,k)) }.join('&') when Array then value.map { |v| encode(v, "#{key}[]") }.join('&') when nil then '' else "#{key}=#{CGI.escape(value.to_s)}" end end private def self.append_key(root_key, key) root_key.nil? ? key : "#{root_key}[#{key.to_s}]" end end 
在这里汇总为gem: https : //github.com/simen/queryparams
我喜欢用这个gem:
https://rubygems.org/gems/php_http_build_query
示例用法:
 puts PHP.http_build_query({"a"=>"b","c"=>"d","e"=>[{"hello"=>"world","bah"=>"black"},{"hello"=>"world","bah"=>"black"}]}) # a=b&c=d&e%5B0%5D%5Bbah%5D=black&e%5B0%5D%5Bhello%5D=world&e%5B1%5D%5Bbah%5D=black&e%5B1%5D%5Bhello%5D=world 
最好的方法是使用Hash.to_params,这是一个很好的数组。
 {a: 1, b: [1,2,3]}.to_params "a=1&b[]=1&b[]=2&b[]=3"