2012-01-03 27 views
19

में कैमेलकेस से सांप_case में नेस्टेड हैश कुंजी को कनवर्ट करना मैं एपीआई रैपर मणि बनाने की कोशिश कर रहा हूं, और जेएसओएन एपीआई रिटर्न से अधिक रूबीश प्रारूप में हैश कुंजी को परिवर्तित करने के साथ समस्याएं हैं।रूबी

JSON घोंसले की कई परतों, दोनों Hashes और सरणी शामिल हैं। मैं क्या करना चाहता हूं कि आसान उपयोग के लिए सभी कुंजी को snake_case में दोबारा परिवर्तित करना है।

यहाँ क्या मैं अब तक मिल गया है: snake_case को

def convert_hash_keys(value) 
    return value if (not value.is_a?(Array) and not value.is_a?(Hash)) 
    result = value.inject({}) do |new, (key, value)| 
    new[to_snake_case(key.to_s).to_sym] = convert_hash_keys(value) 
    new 
    end 
    result 
end 

ऊपर कॉल इस विधि तार कन्वर्ट करने के लिए:

def to_snake_case(string) 
    string.gsub(/::/, '/'). 
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
    gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
    tr("-", "_"). 
    downcase 
end 

आदर्श रूप में, परिणाम निम्न के समान होगा:

hash = {:HashKey => {:NestedHashKey => [{:Key => "value"}]}} 

convert_hash_keys(hash) 
# => {:hash_key => {:nested_hash_key => [{:key => "value"}]}} 

मुझे रिकर्सन गलत मिल रहा है, और इस तरह के समाधान के हर संस्करण में मैंने कोशिश की है पहले स्तर से प्रतीकों को परिवर्तित नहीं करता है, या ओवरबोर्ड चला जाता है और मूल्य सहित पूरे हैश को बदलने की कोशिश करता है।

यदि संभव हो तो वास्तविक हैश और स्ट्रिंग फ़ंक्शंस को संशोधित करने के बजाय, इसे एक सहायक वर्ग में हल करने का प्रयास करना।

अग्रिम धन्यवाद।

+0

कुछ और करने से पहले, 'अगर (नहीं ... और नहीं ...)' डी मॉर्गन के कानून का उपयोग करने के लिए एक आदर्श स्थान है। आपको इसे लिखना चाहिए जब तक ... या ... '। – sawa

उत्तर

31

आप अलग सरणी और हैश के इलाज के लिए की जरूरत है। और, यदि आप रेल में हैं, तो आप अपने होमब्रू to_snake_case के बजाय underscore का उपयोग कर सकते हैं। सबसे पहले एक छोटे से सहायक शोर को कम करने:

def underscore_key(k) 
    k.to_s.underscore.to_sym 
    # Or, if you're not in Rails: 
    # to_snake_case(k.to_s).to_sym 
end 

अपने Hashes कुंजी है कि प्रतीक नहीं हैं या स्ट्रिंग्स तो आप underscore_key उचित रूप से संशोधित कर सकते हैं होगा।

यदि आपके पास ऐरे है, तो आप केवल convert_hash_keys को ऐरे के प्रत्येक तत्व पर लागू करना चाहते हैं; यदि आपके पास हैश है, तो आप underscore_key के साथ चाबियाँ ठीक करना चाहते हैं और प्रत्येक मान के लिए convert_hash_keys लागू करें; यदि आप कुछ और ही है तो आप अछूता के माध्यम से इसे पारित करना चाहते हैं:

def convert_hash_keys(value) 
    case value 
    when Array 
     value.map { |v| convert_hash_keys(v) } 
     # or `value.map(&method(:convert_hash_keys))` 
    when Hash 
     Hash[value.map { |k, v| [underscore_key(k), convert_hash_keys(v)] }] 
    else 
     value 
    end 
end 
+0

एक आकर्षण की तरह काम करता है। बहुत धन्यवाद। मैं रेल में ऐसा नहीं कर रहा हूं, लेकिन मेरा मानना ​​है कि मैंने 'to_snake_case' के लिए उपयोग किया गया कोड रेल' अंडरस्कोर 'विधि से आता है। –

+0

@Andrew: 'to_snake_case' में 'string.gsub (/ :: /,'/')' मुझे लगता है कि आप सही हैं कि' to_snake_case' कहां से आया है। एसओ में आपका स्वागत है, अपने प्रवास का आनंद लें। –

+0

रेल का उपयोग करना आवश्यक नहीं है, केवल ActiveSupport, जो हमें नियमित रूप से चेरी-चुनने देता है। 'आवश्यकता' सक्रिय_support/core_ext/string/inflections 'को यह करना चाहिए:' 'FooBar'underscore => "foo_bar" '। –

3

द्वारा स्वीकार कर लिया जवाब 'म्यू बहुत छोटा है' एक मणि में बदल दिया गया, futurechimp के Plissken:

https://github.com/futurechimp/plissken/blob/master/lib/plissken/ext/hash/to_snake_keys.rb

ऐसा लगता है कि इसे रेल के बाहर काम करना चाहिए क्योंकि अंडरस्कोर कार्यक्षमता शामिल है। snake_case को CamelCase:

साथ हैश उदाहरण:

17

आप रेल का उपयोग करते हैं

hash = { camelCase: 'value1', changeMe: 'value2' } 

hash.transform_keys { |key| key.to_s.underscore } 
# => { "camel_case" => "value1", "change_me" => "value2" } 

स्रोत: http://apidock.com/rails/v4.0.2/Hash/transform_keys

नेस्टेड विशेषताओं के लिए transform_keys के बजाय deep_transform_keys उपयोग करते हैं, उदाहरण:

hash = { camelCase: 'value1', changeMe: { hereToo: { andMe: 'thanks' } } } 

hash.deep_transform_keys { |key| key.to_s.underscore } 
# => {"camel_case"=>"value1", "change_me"=>{"here_too"=>{"and_me"=>"thanks"}}} 

स्रोत: http://apidock.com/rails/v4.2.7/Hash/deep_transform_keys

+0

यह केवल हैश के पहले स्तर को बदलता है, नेस्टेड हैश कुंजी अभी भी ऊंट के मामले के रूप में बनी हुई है। – nayiaw

+1

ध्यान के लिए धन्यवाद मैंने अपना जवाब अपडेट किया। –

+0

एक आकर्षण की तरह काम करता है, धन्यवाद! – born4new

0

आप active_support पुस्तकालय का उपयोग कर रहे हैं, तो आप deep_transform_keys उपयोग कर सकते हैं! इस तरह:

hash.deep_transform_keys! do |key| 
    k = key.to_s.snakecase rescue key 
    k.to_sym rescue key 
end