2011-02-03 19 views
6

मेरे पास एक धारावाहिक JSON स्ट्रिंग (वास्तव में शेफ भूमिका परिभाषा) है और इसमें एक json_class कुंजी है, जिससे रूबी JSON पार्सर इसे शेफ :: रोल ऑब्जेक्ट के रूप में मजबूर करने का प्रयास करता है। मैं पार्सर को इस कुंजी को अनदेखा कैसे कर सकता हूं और बस एक सामान्य हैश में बस deserialize कर सकते हैं?रूबी JSON पार्सर को json_class को अनदेखा कैसे करें?

उत्तर

14

मैं सिर्फ एक ही समस्या थी, और JSON मणि के स्रोत को पढ़ कर जवाब मिला - पार्स करने के लिए प्रयास करने से पहले बस को सेट किए बिना JSON.create_id:

JSON.create_id = nil 
JSON.parse('{ "json_class": "Chef::Role" }').class => Hash 

संपादित करें: ध्यान दें कि जब से मणि के संस्करण 1.7 (1.8.0 वर्तमान है क्योंकि मैं इस अद्यतन को टाइप करता हूं), उपर्युक्त हैक अब आवश्यक नहीं है। JSON#parse अब json_class को अनदेखा करता है, और JSON#load का उपयोग अनमर्शलिंग डंप किए गए ऑब्जेक्ट्स के बजाय किया जाना चाहिए।

+1

वाह, यह एक हैक जैसा दिखता है, लेकिन यह वास्तव में प्रलेखित एपीआई है: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#create_id – jes5199

0

आप पार्सिंग से पहले स्ट्रिंग पर gsub कर सकते हैं, और उस विशेष कुंजी को किसी और चीज़ में बदल सकते हैं।

JSON का नमूना पहले और बाद में दिखाने के बारे में कैसे?

6

"json_class" कुंजी यह इंगित करने के लिए है कि ऑब्जेक्ट जेसन को किस तरह से मार्शल किया जाना चाहिए। यह JSON.dump द्वारा जोड़ा गया है। JSON के नवीनतम संस्करणों में, JSON.parse "json_class" को अनदेखा कर देगा, एक हैश के लिए गैर-मार्शलिंग। जबकि JSON.load संकेतित वस्तु के लिए अन-मार्शल होगा (आपके मामले में, एक शेफ :: भूमिका)।

JSON.parse('{ "json_class": "Chef::Role" }').class => Hash 
JSON.load('{ "json_class": "Chef::Role" }').class => Chef::Role 
+0

धन्यवाद अद्यतन के लिए, मैट। मैंने भविष्य में passersby के लिए प्रतिबिंबित करने के लिए अपना जवाब संपादित कर दिया है। –

0

डॉक्स के अनुसार, मार्क रीड की समाधान निश्चित रूप से काम करना चाहिए। लेकिन जब मैं एक Vagrantfile में यह करने की कोशिश की:

JSON.create_id = nil 
vagrant_json = JSON.parse(Pathname(__FILE__).dirname.join('nodes', "#{node_name}.json").read) 

config.vm.provision :chef_solo do |chef| 
    chef.cookbooks_path = ["cookbooks", "site-cookbooks"] 
    chef.roles_path = "roles" 
    chef.data_bags_path = "data_bags" 
    chef.node_name = node_name 
    chef.run_list = vagrant_json.delete('run_list') 
    chef.json = vagrant_json 
end 

vagrant_json.class एक हैश किया गया था, लेकिन यह अभी भी json_class मूल्य आंतरिक रूप से बनाए रखा जब भी node.json फ़ाइल "json_class" निहित: "बावर्ची :: नोड " प्रविष्टि। फिर आखिरी पंक्ति में chef.json मान को सेट करने के लिए हैश का उपयोग करते समय, इसे फिर से जेसन क्लास (और परिणाम, अजीब, एक खाली रन सूची का उपयोग करके व्याख्या किया गया था।)

यहां क्या काम किया गया है। एक ही विचार है, लेकिन थोड़ा कम चालाकी:

vagrant_json = JSON.parse(Pathname(__FILE__).dirname.join('nodes', "#{node_name}.json").read) 
vagrant_json['json_class'] = nil # <== This worked 

config.vm.provision :chef_solo do |chef| 
    chef.cookbooks_path = ["cookbooks", "site-cookbooks"] 
    chef.roles_path = "roles" 
    chef.data_bags_path = "data_bags" 
    chef.node_name = node_name 
    chef.run_list = vagrant_json.delete('run_list') 
    chef.json = vagrant_json 
end 

इस कोड, दोनों json गुण और एक बावर्ची नोड फ़ाइल से रन सूची सेट करने के लिए काम के साथ या "json_class" बिना: "बावर्ची :: नोड" प्रवेश।

संक्षेप में, पिछले उत्तर JSON.parse से हैश प्राप्त करने के संबंध में पूरी तरह से सही प्रतीत होता है, लेकिन यदि आप उस हैश से json_class जोड़ी को नहीं हटाते हैं, तो इस मामले में अभी भी समस्या हो सकती है ।