2011-09-25 24 views
50

चलें कहते हैं कि मैं इस हैश है:रूबी JSON पार्स हैश कुंजी बदलता है

{ 
    :info => [ 
    { 
     :from => "Ryan Bates", 
     :message => "sup bra", 
     :time => "04:35 AM" 
    } 
    ] 
} 

मैं hash[:info] करके जानकारी सरणी कॉल कर सकते हैं। अब

{ 
    "info" => [ 
    { 
     "from" => "Ryan Bates", 
     "message" => "sup bra", 
     "time" => "04:35 AM" 
    } 
    ] 
} 

अगर मैं hash[:info] यह रिटर्न nil उपयोग करें, लेकिन नहीं:

अब जब मैं JSON (JSON.generate) में इस बारी है, और फिर इसे (JSON.parse) को पार्स, मैं इस हैश मिल अगर मैं hash["info"] का उपयोग करता हूं।

यह क्यों है? और क्या इस असंगतता को ठीक करने के लिए वैसे भी है (शुरुआत से स्ट्रिंग कुंजियों का उपयोग करने के अलावा)?

उत्तर

19

संक्षेप में, नहीं। इस बारे में सोचें, जेएसओएन में प्रतीकों को संग्रहीत करना जेएसओएन में तारों को संग्रहित करने जैसा ही है। इसलिए जब आप जेएसओएन स्ट्रिंग को पार्स करने की बात आती है तो आप दोनों के बीच संभवतः अंतर नहीं कर सकते हैं। आप निश्चित रूप से स्ट्रिंग कुंजियों को प्रतीकों में परिवर्तित कर सकते हैं, या वास्तव में जेएसओएन के साथ बातचीत करने के लिए एक वर्ग भी बना सकते हैं जो यह स्वचालित रूप से करता है, लेकिन मैं केवल तारों का उपयोग करने की अनुशंसा करता हूं।

what is the best way to convert a json formatted key value pair to ruby hash with symbol as key?

ActiveSupport::JSON decode hash losing symbols

या शायद एक HashWithIndifferentAccess

+0

लिंक के लिए धन्यवाद, लेकिन जैसे आपने कहा था, मैं सिर्फ चाबी के लिए तार का उपयोग करेंगे – LanguagesNamedAfterCofee

118

:

लेकिन, बस इसे के लिए, यहाँ इस सवाल का जवाब पिछले बार यह कहा गया है कर रहे हैं JSON जनरेटर प्रतीकों को तारों में परिवर्तित करता है क्योंकि JSON प्रतीकों का समर्थन नहीं करता है। चूंकि JSON कुंजी सभी तार हैं, इसलिए एक JSON दस्तावेज़ को पार्स करने से डिफ़ॉल्ट रूप से स्ट्रिंग कुंजियों के साथ रूबी हैश उत्पन्न होगा।

आप पार्सर को symbolize_names विकल्प का उपयोग करके तारों के बजाय प्रतीकों का उपयोग करने के लिए कह सकते हैं।

उदाहरण:

original_hash = {:info => [{:from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM"}]} 
serialized = JSON.generate(original_hash) 
new_hash = JSON.parse(serialized, {:symbolize_names => true}) 

new_hash[:info] 
#=> [{:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}] 

संदर्भ: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-parse

+0

जानकारी के लिए धन्यवाद :) – LanguagesNamedAfterCofee

+0

और मुझे लगता है कि यह है: symbolize_keys अब (http://rubydoc.info/gems/multi_json/1.3.2/MultiJson) – Boushley

+9

@ बुशले: नहीं, यह अभी भी 'symbolize_names' है। मेरा जवाब जेएसओएन इंजन का संदर्भ देता है जो रूबी मानक पुस्तकालय के साथ जहाजों। आप किसी तीसरे पक्ष के मणि का संदर्भ दे रहे हैं। – wyattisimo

2
  1. उपयोग ActiveSupport :: JSON.decode, तो यह आपको json पारसर्स स्वैप करने के लिए अनुमति देगा आसान
  2. उपयोग ActiveSupport :: JSON.decode (my_json, symbolize_names: true)

यह हैश में सभी कुंजियों का पुनरावृत्ति का प्रतीक होगा।

(रूबी 2 पर पुष्टि की गई।0)

+0

रेल 4.1 में हटाया जा रहा प्रतीत होता है? http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#changes-in-json-handling और http://api.rubyonrails.org/classes/ActiveSupport/JSON.html राज्य विकल्प समर्थन हटा दिया गया – nruth

4

मैं इस पर with_indifferent_access विधि बुला के साथ मेरे समान समस्या हल हो जाती

यहाँ मैं एक json स्ट्रिंग है और हम चर रों

s = "{\"foo\":{\"bar\":\"cool\"}}" 

तो को असाइन कर सकें अब मैं डेटा पार्स कर सकते हैं JSON वर्ग के साथ है और यह ज

h = JSON.parse(s).with_indifferent_access 

यह एक हैश कि एक स्ट्रिंग या कुंजी

के रूप में एक प्रतीक स्वीकार कर सकते हैं का उत्पादन करेगा आवंटित
h[:foo]["bar"] 
    #=> "cool" 
+0

क्या 'with_indifferent_access' जोड़ा गया है रेल पारिस्थितिक तंत्र में कुछ के माध्यम से 'हैश'? – Mark

+1

@ मार्क आप सही हैं। यहां एक लिंक है http://api.rubyonrails.org/v4.2.5/classes/ActiveSupport/HashWithIndifferentAccess.html –

0

आप इस

ActiveSupport::JSON.decode(str_json, symbolize_names: true)

रेल 4.1 या बाद में की तरह है कि विकल्प का उपयोग नहीं कर सकते हैं, ActiveSupport::JSON.decode नहीं रह गया है MultiJSON के लिए एक विकल्प हैश स्वीकार करता है। मल्टीजोन अपने जीवन के अंत तक पहुंच गया और हटा दिया गया है।

आप इसे संभालने के लिए symbolize_keys का उपयोग कर सकते हैं।

ActiveSupport::JSON.decode(str_json).symbolize_keys 
2

यह एक हैश में सभी चाबियाँ संशोधित करने के लिए उन्हें एक तार से एक प्रतीक में बदलने के लिए संभव है:

symbol_hash = Hash[obj.map{ |k,v| [k.to_sym, v] }] 

puts symbol_hash[:info] 
# => {"from"=>"Ryan Bates", "message"=>"sup bra", "time"=>"04:35 AM"} 

दुर्भाग्य है कि हैश सरणी के अंदर नेस्टेड के लिए काम नहीं करता। हालांकि, आप एक छोटे से पुनरावर्ती विधि है कि सभी हैश कुंजी धर्मान्तरित लिख सकते हैं:

def symbolize_keys(obj) 
    #puts obj.class # Useful for debugging 
    return obj.collect { |a| symbolize_keys(a) } if obj.is_a?(Array) 
    return obj unless obj.is_a?(Hash) 
    return Hash[obj.map{ |k,v| [k.to_sym, symbolize_keys(v)] }] 
end 

symbol_hash = symbolize_keys(hash) 
puts symbol_hash[:info] 
# => {:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"} 
संबंधित मुद्दे