রুবি: কীভাবে একটি হ্যাশকে এইচটিটিপি প্যারামিটারে পরিণত করা যায়?


205

প্লেইন হ্যাশের মতো এটি বেশ সহজ

{: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"}]

যে প্রশংসিত সাহায্যের জন্য ধন্যবাদ!


দেখে মনে হচ্ছে আপনি JSON কে HTTP প্যারামে রূপান্তর করতে চান ... সম্ভবত আপনার কোনও আলাদা এনকোডিং দরকার?
কুকিঅফফোর্টুন

হুম, এটি আসলে জসন নয়, তবে একটি রুবি হ্যাশ ... নিশ্চিত নয় যে আমি এখানে কেন এনকোডিংয়ের বিষয়টি বুঝতে পেরেছি।
জুলিয়েন জেনেসটাক্স

Lmanners দ্বারা উত্তর প্রচার করা উচিত। এখানে আপনার নিজের অনেকগুলি দুর্দান্ত রোল রয়েছে (অনেকগুলি উচ্চ স্কোর সহ) তবে অ্যাক্টিভসপোর্টটি এর জন্য কথোপকথনটিকে উপস্থাপন করে এর জন্য প্রমিতীকৃত সমর্থন যোগ করেছে। দুর্ভাগ্যক্রমে, ল্যানম্যানারের উত্তর এখনও তালিকার নীচে রয়েছে।
নোয়াচ ম্যাগডম্যান

2
@ আমার মতে কোনও মন্তব্য নেই, যে কোনও উত্তর যা একটি লাইব্রেরির উপর নির্ভর করতে বলে যে ভারী বানরের মূল ক্লাসগুলি প্যাচ করে রাখা উচিত। এই প্যাচগুলির একটি বিশাল সংখ্যার ন্যায়সঙ্গততা সর্বোপরি নড়বড়ে ( এই নিবন্ধে ইয়াহুদা কাটজের মন্তব্যগুলি দেখুন ) এটি একটি দুর্দান্ত উদাহরণ। ওয়াইএমএমভি, তবে আমার জন্য, ক্লাস পদ্ধতিযুক্ত এমন কিছু যা বা অবজেক্ট এবং হ্যাশ খুলবে না এবং যেখানে লেখকরা "কেবল আমাদের সাথে সংঘর্ষ করবেন না" বলবেন না! অনেক বেশি, আরও ভাল হবে।
আইয়েন

উত্তর:


86

আপডেট: এই কার্যকারিতাটি মণি থেকে সরানো হয়েছিল।

জুলিয়েন, আপনার স্ব-উত্তরটি উত্তম।

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

1
ধন্যবাদ! আমার সমাধানটি ভেঙে যায় এমন প্রান্তগুলি কী কী? সুতরাং আমি চশমা যোগ করতে পারেন?
জুলিয়েন জেনেসটক্স

2
এটি বুলিয়ানগুলি পরিচালনা করে না, এবং এটি পরিষ্কারভাবে অনাকাঙ্ক্ষিত: {"a" => "a & b = b"}। To_params
বব আমান

3
এফওয়াইআই, দুর্ভাগ্যক্রমে এই আচরণটি ঠিকানা থেকে ২.৩ হিসাবে সরানো হয়েছে ( github.com/sporkmonger/addressable/commit/… )
oif_vet

2
@oif_vet আপনি কি বলতে পারবেন কোন আচরণটি সরানো হয়েছে? মূল পোস্টারের সমস্যা সমাধানের জন্য অ্যাড্রেসযোগ্য রত্নটি ব্যবহার করার পরামর্শ ববের পরামর্শ সম্বোধনযোগ্য -২.৩.২ হিসাবে আমার জন্য কাজ করে।
শেলডনহ

1
@ Sheldonh, না, @oif_vet ঠিক আছে। আমি এই আচরণটি সরিয়েছি। গভীরভাবে নেস্টেড স্ট্রাকচারগুলি আর পরিবর্তনকারীকে ইনপুট হিসাবে query_valuesঅ্যাড্রেসেবল সমর্থন করে না ।
বব আমান

269

বেসিক, অ-নেস্টেড হ্যাশগুলির জন্য, রেলস / অ্যাক্টিভসপোর্ট রয়েছে 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


1
তুমি কেন বলছ যে এটা ভেঙে গেছে? আপনি যে আউটপুট দেখিয়েছেন তা ঠিক আছে, তাই না?
টোকল্যান্ড

আমি এটি চেষ্টা করেছি এবং আপনি ঠিক বলে মনে করছেন। আমার বক্তব্যটি মূলত রেলগুলির পূর্ববর্তী সংস্করণটি কোয়েরি স্ট্রিংকে পার্স করার কারণে হয়েছে (আমি এটি আগের 'বি' মানগুলি ওভাররাইটিং করে মনে করেছিলাম)। 2011-03-10 11:19:40 এ -0600- এ সাইটগুলি নিয়ন্ত্রক # সূচক দ্বারা প্রসেসিং হিসাবে 127.0.0.1 এ "/? এ = বি এবং% 5 বি% 5 ডি = সি এবং বি% 5 বি% 5 ডি = ডি ও বি% 5 বি% 5 ডি = ই" শুরু হয়েছে এইচটিএমএল প্যারামিটার: {"a" => "এ", "বি" => ["সি", "ডি", "ই"]}
গ্যাবে মার্টিন-ড্যাম্পেসি

নেস্টেড হ্যাশ থাকলে কী ভুল হয়? নেস্টেড হ্যাশগুলি থাকাকালীন কেন আমি এটি ব্যবহার করতে পারি না? আমার কাছে, এটি কেবল url নেস্টেড হ্যাশ থেকে পালাতে পারে, HTTP অনুরোধে এটি ব্যবহার করতে কোনও সমস্যা হবে না।
স্যাম

2
বিনা ব্যতীত: require 'active_support/all'প্রয়োজনীয়
ডোরিয়ান

কমপক্ষে রেল 5.2 দিয়ে to_queryনীল মানগুলি সঠিকভাবে পরিচালনা করে না। { a: nil, b: '1'}.to_query == "a=&b=1", তবে র্যাক এবং সিজিআই উভয়ই a=খালি স্ট্রিং হিসাবে পার্স করে , না nil। আমি অন্যান্য সার্ভারগুলির জন্য সমর্থন সম্পর্কে নিশ্চিত নই, তবে রেলের সাথে সঠিক কোয়েরি স্ট্রিংটি হওয়া উচিত a&b=1। আমি মনে করি এটি ভুল যে
রেলগুলি

153

আপনি যদি রুবি ১.৯.২ বা তার পরে ব্যবহার করছেন URI.encode_www_formতবে আপনার অ্যারে দরকার না হলে আপনি ব্যবহার করতে পারেন ।

উদাহরণস্বরূপ (1.9.3 এ রুবি ডক্স থেকে):

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ব্যবহার করে তা হ'ল application/x-www-form-urlencodedডেটা HTML5 সংজ্ঞা অনুসারে ।


8
+1, এটি এখন পর্যন্ত সেরা। এটি রুবির বাইরে কোনও উত্সের উপর নির্ভর করে না।
ড্যানিয়েল

+1 '{: a => "এ",: বি => {: সি => "সি",: ডি => সত্য},: ই => []}' উদাহরণ দিয়ে
ডিউক কাজ করে

1
রুবি ২.০ নিয়ে কাজ করছে বলে মনে হচ্ছে না - হ্যাশটি {:c => "c", :d => true}পরিদর্শন করা হয়েছে বলে মনে হয়, তাই স্ট্রিং হিসাবে পাঠানো হয়েছিল।
ব্যবহারকারী 208769

1
এটি উপরের বৃহত্তর স্নিপেটের একটি অংশ ছিল -ruby -ruri -e 'puts RUBY_VERSION; puts URI.encode_www_form({:a => "a", :b => {:c => "c", :d => true}, :e => []})' # outputs 2.0.0 a=a&b=%7B%3Ac%3D%3E%22c%22%2C+%3Ad%3D%3Etrue%7D&
ব্যবহারকারী 208769

1
নোট করুন যে এটি Addressable::URIএবং অ্যাক্টিভসপোর্টের উভয়ের চেয়ে অ্যারে মানের জন্য পৃথক ফলাফল রয়েছে Object#to_query
ম্যাট হাগিনস

61

ফুলে যাওয়া অ্যাক্টিভসপোর্টটি লোড করার বা আপনার নিজস্ব রোল করার দরকার নেই, আপনি ব্যবহার করতে পারেন 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"}]}

আপনার নেস্টেড উদাহরণটি প্রমাণ করে যে এটি সঠিকভাবে কাজ করে না - আপনি যখন শুরু করেন, তখন :bদুটি হ্যাশের অ্যারে হয়। আপনি :bএকটি বড় হ্যাশ এর অ্যারে হয়ে শেষ ।
এড রডার

3
@ এড্রুডার সঠিকভাবে নেই কারণ গ্রহণযোগ্য মান নেই। এটি যা দেখায় তা হ'ল এটি অন্য কারও চেষ্টা থেকে অনেক বেশি কাছাকাছি, অন্য উত্তরগুলির দ্বারা বিচার করা।
iain

1
এই পদ্ধতিটি ব্যর্থ 2.3.8 সাল থেকে অবচিত করা হয়েছে: apidock.com/rails/Rack/Utils/build_query
ডেভিডগোলি

8
@ ডেভিডগোলি এর্ম, র্যাকের মধ্যে নেই এটি গিথুব . com/rack/rack/blob/1.5.2/lib/rack/utils.rb#L140 নয় । আপনি যদি এটি রিলে ব্যবহার করতে চান তবে অবশ্যই এটি এতটা সহজ require 'rack'? এটি অবশ্যই সেখানে থাকা উচিত, সমস্ত বড় রুবি ওয়েব ফ্রেমওয়ার্কগুলি র্যাকের শীর্ষে এখন নির্মিত considering
আইইন

@ এড্রুডার অ্যাক্টিভসপোর্টগুলিও to_query2 অ্যারে (ভি 4.2 ) মার্জ করে।
কেলভিন

9

মার্ব থেকে চুরি করুন:

# 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/de વિકાસment/merb/hash/to_params.html দেখুন


1
দুর্ভাগ্যক্রমে, যখন আমাদের প্যারামগুলির ভিতরে নেস্টেড অ্যারে থাকবে তখন এই কাজটি করা হয়নি (উদাহরণ দেখুন # 2) ... :(
জুলিয়েন জেনেসটক্স

2
এবং পালানোর কোনও রাজা করে না।
আর্নেস্ট

9

আপনার যদি কেবলমাত্র সহজ 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"

4
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

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

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

এখানে অন্য উপায়। সাধারণ প্রশ্নের জন্য।


2
আপনার সত্যিকারের নিশ্চিত হওয়া উচিত যে আপনি নিজের কী এবং মানগুলি যথাযথভাবে ইউআরআই-থেকে বেরিয়ে আসছেন। এমনকি সাধারণ ক্ষেত্রে। এটি আপনাকে কামড় দেবে
জ্রোকাইন্ড

2

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি কেবল এই বিট কোডটি পোস্ট করতে চেয়েছিলাম কারণ আমার পক্ষে এই কাজটি করার কোনও সাধারণ রত্ন খুঁজে পেল না।

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


1
URI.escape != CGI.escapeএবং URL এর জন্য আপনি প্রথমটি চান।
আর্নেস্ট

2
আসলে না, @ আর্নেস্ট। উদাহরণস্বরূপ যখন আপনার ইউআরএলকে প্যারামিটার হিসাবে অন্য url এম্বেড করা হয় (আসুন আমরা লগইন করার পরে পুনর্নির্দেশের url url বলতে পারি) ইউআর.আই.স্ক্যাপটি 'রাখবে?' এবং এম্বেড থাকা url- এর '&' জায়গায় আশেপাশের ইউআরএলটি ভেঙে ফেলা হয়, অন্যদিকে সিজিআই.সেস্কেপ তাদের যথাযথভাবে% 3F এবং% 26 হিসাবে সরিয়ে ফেলবে। CGI.escape("http://localhost/search?q=banana&limit=7") => "http%3A%2F%2Flocalhost%2Fsearch%3Fq%3Dbanana%26limit%3D7" URI.escape("http://localhost/search?q=banana&limit=7") => "http://localhost/search?q=banana&limit=7"
সোভেল

2

এটি হ্যাশ.টো_প্রেমগুলি ব্যবহার করা সবচেয়ে ভাল পদ্ধতির যা অ্যারেগুলির সাথে কাজ করে।

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

বিনা ব্যতীত: require 'active_support/all'প্রয়োজনীয়
ডোরিয়ান

1

যদি আপনি কোনও ফ্যারাডে অনুরোধের প্রসঙ্গে থাকেন তবে দ্বিতীয় যুক্তি হিসাবে এবং ফ্যারাডে সঠিক প্যারাম ইউআরএল অংশটি তৈরির যত্ন নেওয়ার কারণে আপনি কেবল পারম হ্যাশটি পাস করতে পারেন:

faraday_instance.get(url, params_hsh)

0

আমি এই রত্নটি ব্যবহার করতে পছন্দ করি:

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

0
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"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.