programing

루비: 해시를 HTTP 매개 변수로 변환하는 방법은?

css3 2023. 6. 14. 22:08

루비: 해시를 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"}]

도와주셔서 감사합니다!

중첩되지 않은 기본 해시의 경우 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"

배열 값은 다음을 포함하는 키 이름으로 설정되지 않습니다.[]우리 모두가 쿼리 문자열에 익숙해진 것처럼.사양은encode_www_form사용은 의 HTML5 정의를 따릅니다.application/x-www-form-urlencoded데이터.

업데이트: 이 기능이 보석에서 제거되었습니다.

줄리앙, 당신의 자답은 좋은 것이고, 나는 뻔뻔스럽게도 그것을 빌렸지만, 예약된 인물들로부터 제대로 빠져나오지 못하고, 그 외에도 몇 가지의 에지 케이스가 고장이 납니다.

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 install addressable

확장된 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"}]}

단순한 ASCII 키/값 쿼리 문자열만 지원하면 되는 경우에는 짧고 달콤한 하나의 라이너가 있습니다.

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"

머브에서 훔치기:

# 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 을 참조하십시오.

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

이것이 오래된 질문인 것은 알지만, 저를 위해 이 작업을 수행할 간단한 보석을 찾을 수 없었기 때문에 이 코드를 게시하고 싶었습니다.

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

여기서 보석으로 롤업: https://github.com/simen/queryparams

{:a=>"a", :b=>"b", :c=>"c"}.map{ |x,v| "#{x}=#{v}" }.reduce{|x,v| "#{x}&#{v}" }

"a=a&b=b&c=c"

다른 방법이 있습니다.단순 쿼리용입니다.

가장 좋은 방법은 어레이에서 잘 작동하는 Hash.to _params를 사용하는 것입니다.

{a: 1, b: [1,2,3]}.to_param
"a=1&b[]=1&b[]=2&b[]=3"
require 'uri'

class Hash
  def to_query_hash(key)
    reduce({}) do |h, (k, v)|
      new_key = key.nil? ? k : "#{key}[#{k}]"
      v = Hash[v.each_with_index.to_a.map(&:reverse)] if v.is_a?(Array)
      if v.is_a?(Hash)
        h.merge!(v.to_query_hash(new_key))
      else
        h[new_key] = v
      end
      h
    end
  end

  def to_query(key = nil)
    URI.encode_www_form(to_query_hash(key))
  end
end

2.4.2 :019 > {:a => "a", :b => "b"}.to_query_hash(nil)
 => {:a=>"a", :b=>"b"}

2.4.2 :020 > {:a => "a", :b => "b"}.to_query
 => "a=a&b=b"

2.4.2 :021 > {:a => "a", :b => ["c", "d", "e"]}.to_query_hash(nil)
 => {:a=>"a", "b[0]"=>"c", "b[1]"=>"d", "b[2]"=>"e"}

2.4.2 :022 > {:a => "a", :b => ["c", "d", "e"]}.to_query
 => "a=a&b%5B0%5D=c&b%5B1%5D=d&b%5B2%5D=e"

패러데이 요청의 컨텍스트에 있는 경우, 두 번째 인수로 매개 변수 해시를 전달하면 패러데이가 적절한 매개 변수 URL 부분을 만드는 것을 처리할 수도 있습니다.

faraday_instance.get(url, params_hsh)

나는 이 보석을 사용하는 것을 좋아합니다.

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
2.6.3 :001 > hash = {:a => "a", :b => ["c", "d", "e"]}
=> {:a=>"a", :b=>["c", "d", "e"]}
2.6.3 :002 > hash.to_a.map { |x| "#{x[0]}=#{x[1].class == Array ? x[1].join(",") : x[1]}" 
}.join("&")
=> "a=a&b=c,d,e"

언급URL : https://stackoverflow.com/questions/798710/ruby-how-to-turn-a-hash-into-http-parameters