2010-01-13 17 views
22

मैं समझता हूं कि JSON में, कुंजी को डबल कोट्स में घिरा होना चाहिए। हालांकि, मैं एक डेटा स्रोत का उपयोग कर रहा हूं जो उन्हें उद्धृत नहीं करता है, जो रूबी जेएसओएन पार्सर को एक त्रुटि उठाने का कारण बन रहा है। क्या 'गैर-सख्त' पार्सिंग करने का कोई तरीका है?उद्धृत कुंजी के बिना JSON पार्सिंग

उदाहरण:

>> JSON.parse('{name:"hello", age:"23"}') 
JSON::ParserError: 618: unexpected token at '{name:"hello", age:"23"}' 
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse' 
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse' 
    from (irb):5 
>> JSON.parse('{"name":"hello", "age":"23"}') 
=> {"name"=>"hello", "age"=>"23"} 
>> 

(मैं पार्स करने से पहले में उद्धरण जोड़ने के लिए एक नियमित अभिव्यक्ति का उपयोग कर की कोशिश की लेकिन नहीं यह पूरी तरह से काम करना आरंभ कर सकता है)।

+9

यदि यह JSON नहीं है, तो यह JSON नहीं है। यह अधिसूचनात्मक रूप से इसके समान हो सकता है, लेकिन सही समाधान स्रोत को ठीक करना है, इसलिए यह वास्तव में JSON isntead देता है-जो-दिखता है-जैसा-जेएसओएन-लेकिन-नहीं है। –

+0

दुर्भाग्यवश मेरे पास स्रोत पर कोई नियंत्रण नहीं है, यह किसी तीसरे पक्ष से है। उदाहरण के लिए –

+0

http://www.google.com/ig/calculator?hl=hi&q=100AUD=?USD की आवश्यकता है कि वह क्या मांग रहा है। @floyd के नीचे समाधान है - और स्वीकार्य है – Rabbott

उत्तर

15

डेटा बहुत अच्छी तरह से है कि अन्य की तुलना में गठन किया गया है, एक सरल regex कर सकता यह: - क्योंकि मेरे तार में से कुछ कोलन शामिल यह असफल रहा था (मेरे अपने प्रश्न का उत्तर देना)

irb(main):009:0> '{name:"hello", age:"23"}'.gsub(/([a-z]+):/, '"\1":') 
=> "{\"name\":\"hello\", \"age\":\"23\"}" 
+5

'' नाम: "हैलो", आयु: "23"} 'gsub (/ ([\ w] +): /, '"\ 1":') 'इसे थोड़ा और मजबूत बनाता है! – ankimal

+3

मूल्य एक टाइमस्टैम्प है अगर बुरी तरह विफल रहता है। उदाहरण के लिए {name: "हैलो", समय: "12:59:59"} – Prabhakar

6

दिलचस्प बात यह है कि आपका उदाहरण मान्य रूबी 1.9 हैश सिंटैक्स है। यदि आपका डेटा वास्तव में इस तरह सरल है (कुंजी नामों में कोई स्थान या अन्य विशेष वर्ण नहीं), और आप इसे एक सुरक्षित संदर्भ में संसाधित कर सकते हैं, तो आप इसे eval कर सकते हैं। यदि आप उन्हें तार में बदल जाने की जरूरत है

irb(main):001:0> eval '{name:"hello", age:"23"}' 
=> {:name=>"hello", :age=>"23"} 

यह बहुत बाद की प्रक्रिया आप कुंजी के रूप में प्रतीक, देता है:

irb(main):002:0> eval('{name:"hello", age:"23"}').reduce({}) {|h,(k,v)| h[k.to_s] = v; h} 
=> {"name"=>"hello", "age"=>"23"} 
+1

इसके लिए धन्यवाद, हालांकि चूंकि मैं 1.8.7 का उपयोग कर रहा हूं जो फिलहाल एक विकल्प नहीं है। –

+0

बहुत साफ समाधान! धन्यवाद। एक और मणि शिकार करने के बजाय Google से इस जानकारी का लाभ उठाने के लिए बहुत साफ है। – ylluminate

+5

यह बहुत खतरनाक हो सकता है ... (उदाहरण के लिए यदि आप सर्वर से प्राप्त करते हैं '{ए: 1}; \ 'आरएम-आरएफ/\' ') – ghayes

1

स्निपेट है, जो पोस्ट फ्लोयड के लिए इसी तरह मैं क्या करने की कोशिश की थी। लेकिन मैं कायम है और एक समाधान मिला:

gsub(/([\{|\,}])\s*([a-zA-Z]+):/, '\1 "\2":') 
+0

समस्या यह है कि आपका रेगेक्स भी उद्धृत मूल्य के अंदर "कुंजी =" के उदाहरणों को प्रतिस्थापित करेगा, जो कोई नहीं चाहता है। –

2
gsub(/(\w+)\s*:/, '"\1":') 

की तुलना में बेहतर

gsub(/([a-z]+):/, '"\1":') 

काम यदि यह रिक्त स्थान या बड़े अक्षरों था, यह विफल रहा है।

8

मेरे पास एक तीसरी पार्टी डेटा फीड के साथ एक ही समस्या है, लेकिन मेरा एक और जटिल जेएसओएन जैसी प्रतिक्रिया देता है जो gsub समाधान संभाल नहीं करता है। कुछ शोध के बाद ऐसा लगता है कि ये डेटा फ़ीड्स वास्तव में जावास्क्रिप्ट ऑब्जेक्ट अक्षर हैं जिन्हें कुंजी को उद्धृत करने की आवश्यकता नहीं होती है।

समस्या को हल करने के लिए मैंने execjs मणि जोड़ा और node.js स्थापित किया (थर्म्यूराइज़र मणि शायद भी काम करेगा)। एक बार पूरा हो जाने पर, निम्नलिखित सही ढंग से पार्स किए गए रूबी हैश लौटाते हैं।

ExecJS.eval('{name:"hello", age:"23"}') 
=> {"name"=>"hello", "age"=>"23"} 
0

यह मैं इसे कैसे हल करने के लिए पड़ा है है:

JSON.parse(broken_json_string.gsub(/'([^']+)':/, '"\1":')) 

ऊपर से कुछ मान लिया गया कुंजी केवल अक्षर; हमारे कुछ में अंडरस्कोर, रिक्त स्थान इत्यादि शामिल हैं, बस इतना कहना है कि "कोई भी चरित्र जो एक उद्धरण नहीं है" (दिया गया है, हमारे मामले में, सभी चाबियाँ सिंगल कोट्स में लिपटे हैं)।

संबंधित मुद्दे