JSON.parseJSON ने JSON में एकल उद्धरण से बचने के कारण "अमान्य JSON" त्रुटि फेंकी


202

मैं अपने सर्वर का उपयोग करके अनुरोध कर रहा हूं jQuery.post()और मेरा सर्वर JSON ऑब्जेक्ट्स (जैसे { "var": "value", ... }) वापस कर रहा है। हालाँकि, यदि किसी भी मान में एक भी उद्धरण है (ठीक तरह से बच गया है \'), jQuery अन्यथा मान्य JSON स्ट्रिंग को पार्स करने में विफल रहता है। यहां इसका एक उदाहरण है जो मेरा मतलब है ( क्रोम के कंसोल में किया गया है ):

data = "{ \"status\": \"success\", \"newHtml\": \"Hello \\\'x\" }";
eval("x = " + data); // { newHtml: "Hello 'x", status: "success" }

$.parseJSON(data); // Invalid JSON: { "status": "success", "newHtml": "Hello \'x" }

क्या यह सामान्य है? क्या JSON के माध्यम से किसी एक उद्धरण को ठीक से पास करने का कोई तरीका नहीं है?

जवाबों:


325

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

http://www.json.org/string.gif


अद्यतन - रुचि रखने वालों के लिए अधिक जानकारी:


डगलस क्रॉफोर्ड विशेष रूप से यह नहीं कहते हैं कि JSON विनिर्देश स्ट्रिंग्स के भीतर एकल उद्धरण से बचने की अनुमति क्यों नहीं देता है। हालाँकि, जावास्क्रिप्ट के जेंसन ई: द गुड पार्ट्स में जेन्स की अपनी चर्चा के दौरान , वे लिखते हैं:

JSON के डिजाइन लक्ष्य न्यूनतम, पोर्टेबल, पाठ्य और जावास्क्रिप्ट के उपसमुच्चय थे। इंटरपॉर्ट करने के लिए हमें जितना कम सहमत होने की आवश्यकता है, उतनी ही आसानी से हम इंटरोपर्ट कर सकते हैं।

इसलिए शायद उन्होंने केवल दो-उद्धरणों का उपयोग करके स्ट्रिंग को परिभाषित करने की अनुमति देने का फैसला किया क्योंकि यह एक कम नियम है जो सभी JSON कार्यान्वयनों पर सहमत होना चाहिए। नतीजतन, स्ट्रिंग के भीतर एक एकल उद्धरण चरित्र के लिए गलती से स्ट्रिंग को समाप्त करना असंभव है, क्योंकि परिभाषा के अनुसार एक स्ट्रिंग को केवल दोहरे-भाव वाले चरित्र द्वारा समाप्त किया जा सकता है। इसलिए औपचारिक विनिर्देश में एकल उद्धरण चरित्र से बचने की अनुमति देने की आवश्यकता नहीं है।


थोड़ा और गहरा खोदते हुए , Crockford's org.json जावा के लिए JSON का कार्यान्वयन अधिक स्वीकार्य है और यह आपके उद्धरण की अनुमति देता है:

स्टर्लिंग विधियों द्वारा निर्मित ग्रंथों को JSON सिंटैक्स नियमों के कड़ाई से अनुरूप है। निर्माता उन ग्रंथों में अधिक क्षमा कर रहे हैं जिन्हें वे स्वीकार करेंगे:

...

  • स्ट्रिंग्स को 'एकल उद्धरण' के साथ उद्धृत किया जा सकता है।

JSONTokener स्रोत कोड द्वारा इसकी पुष्टि की गई है । nextStringविधि बच गए एकल उद्धरण वर्ण और बस डबल उद्धरण वर्ण की तरह व्यवहार करता है उन्हें स्वीकार करता है:

public String nextString(char quote) throws JSONException {
    char c;
    StringBuffer sb = new StringBuffer();
    for (;;) {
        c = next();
        switch (c) {

        ...

        case '\\':
            c = this.next();
            switch (c) {

            ...

            case '"':
            case '\'':
            case '\\':
            case '/':
                sb.append(c);
                break;
        ...

विधि के शीर्ष पर एक जानकारीपूर्ण टिप्पणी है:

औपचारिक JSON प्रारूप एकल उद्धरणों में तार की अनुमति नहीं देता है, लेकिन कार्यान्वयन को उन्हें स्वीकार करने की अनुमति है।

इसलिए कुछ कार्यान्वयन एकल उद्धरण स्वीकार करेंगे - लेकिन आपको इस पर भरोसा नहीं करना चाहिए। कई लोकप्रिय कार्यान्वयन इस संबंध में काफी प्रतिबंधात्मक हैं और JSON को अस्वीकार कर देंगे जिसमें एकल उद्धृत स्ट्रिंग्स और / या एकल उद्धरण शामिल हैं।


अंत में इसे मूल प्रश्न पर वापस टाई करने के लिए, jQuery.parseJSONपहले ब्राउज़र के देशी JSON पार्सर या लोड किए गए पुस्तकालय जैसे कि json2.js का उपयोग करने का प्रयास करते हैं, जहां लागू होता है (जो कि एक तरफ ध्यान दें कि लाइब्रेरी jQuery तर्क पर आधारित है यदि JSONपरिभाषित नहीं है) । इस प्रकार jQuery केवल उस अंतर्निहित कार्यान्वयन के रूप में अनुमत हो सकता है:

parseJSON: function( data ) {
    ...

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

    ...

    jQuery.error( "Invalid JSON: " + data );
},

जहां तक ​​मुझे पता है कि ये कार्यान्वयन केवल आधिकारिक JSON विनिर्देशन का पालन करते हैं और एकल उद्धरण स्वीकार नहीं करते हैं, इसलिए न तो jQuery करता है।


4
अद्यतन :: JSON को पेस करते समय JQuery बहुत प्रतिबंधक है। यदि आप चेतावनी का प्रयास करते हैं ($। ParseJSON ("[\" Ciao \\ '\ "]")); जस्टिन की रिपोर्ट के अनुसार यह काम नहीं करता है
daitangio

2
" क्रॉकफ़ोर्ड्स org.json जावा के लिए JSON का कार्यान्वयन अधिक स्वीकार्य है और एकल उद्धरण वर्णों की अनुमति देता है " # यह सिर्फ अच्छा अभ्यास है: मजबूती सिद्धांत
डंकन जोन्स

1
@DuncanJones - यह लेख इस बात की जानकारी दे सकता है कि कोई भी ब्राउज़र उस सिद्धांत का पालन क्यों नहीं करता है जो JSON के संबंध में है: joelonsoftware.com/items/2008/03/17.html
जस्टिन

1
@JustinEthier जैसा कि इस उत्तर द्वारा बताया गया है stackoverflow.com/a/25491642/759452 , JSON कल्पना टूल्स.ietf.org/html/rfc7159 कहता है Any character may be escaped, यह समझा सकता है कि क्यों कुछ कार्यान्वयन एकल उद्धरण से बचने की अनुमति देंगे।
एड्रिन बी

1
@ AdrienBe - दिलचस्प ... लेकिन क्या उनका मतलब किसी भी चरित्र से बच सकता है अगर इसमें 4 हेक्स अंक होते हैं? ऊपर दिए गए राज्य आरेख और आरएफसी की धारा 7 में से एक के अनुसार, लिखित रूप में एक भी उद्धरण से बचने की \'अनुमति नहीं है। इस बिंदु पर आरएफसी अधिक स्पष्ट हो तो अच्छा होगा।
जस्टिन एथियर

15

यदि आपको किसी स्ट्रिंग के अंदर एक एकल उद्धरण की आवश्यकता है, क्योंकि \ n युक्ति द्वारा अपरिभाषित है, तो उन सभी के लिए http://www.utf8-chartable.de/\u0027 देखें

संपादित करें: कृपया टिप्पणियों में मेरे शब्द के गलत उपयोग का बहाना करें। मेरा मतलब बैकस्लैश था। यहाँ मेरा कहना यह है कि इस घटना में आपने अन्य तार के अंदर तारों को घोंसला बनाया है, मुझे लगता है कि एकल उद्धरण से बचने के लिए कई बैकस्लैश के बजाय यूनिकोड का उपयोग करना अधिक उपयोगी और पठनीय हो सकता है। यदि आप नेस्टेड नहीं हैं, लेकिन यह वास्तव में आसान है तो वहां एक पुराने पुराने उद्धरण को रखना आसान है।


29
नहीं, बस एक सादा एकल उद्धरण का उपयोग करें।
जेफ कॉफमैन

कभी-कभी, टन-बैक टिक्स की तुलना में यूनिकोड का उपयोग करना आसान होता है। विशेष रूप से जब बारी-बारी से टिक-टिक के अंदर।
13

3
आपको बैकटिक्स की आवश्यकता क्यों होगी? यदि आपके पास "फू 'बार'" जैसा एक तार है तो आप केवल एकल उद्धरणों को छोड़ देते हैं।
जेफ कॉफमैन

3
ठीक वही जो मेरे द्वारा खोजा जा रहा था। मैं एक js string var के रूप में एक पेज पर एक json स्ट्रिंग लिखने की कोशिश कर रहा हूँ और इसे सिंगल कोट्स में संलग्न कर रहा हूँ और जब भी किसी प्रॉपर्टी की वैल्यू इसमें सिंगल कोटे की थी, तो इसे जल्दी समाप्त कर दिया गया। अब मैं पृष्ठ पर लिखने से पहले कोड में सिर्फ एक json.Replace ("" "," \ u0027 ") करता हूं।
जक

@Zack आपको JSON को उद्धरण के साथ संलग्न नहीं करना चाहिए। यदि आपको मौजूदा JSON स्ट्रिंग से स्ट्रिंग की आवश्यकता है, तो इसे फिर से स्ट्रिंग करें। PHP में, यह वह जगह होगी var jsonEncodedAsString = <?= json_encode(myEncodedJson) ?>जहां myEncodedJsonएक पिछले का परिणाम होता है जो json_encodeआपके एकल उद्धरण से बचने का ध्यान रखेगा, वास्तव में, यह सिर्फ दोहरे उद्धरण चिह्नों में लिपटे एक बड़े स्ट्रिंग को आउटपुट करेगा, इसलिए एकल उद्धरण से बच नहीं जाएगा, लेकिन दोहरे उद्धरण मर्जी।
जुआन मेंडेस

5

मैं समझता हूं कि समस्या कहां है और जब मैं ऐनक देखता हूं तो यह स्पष्ट होता है कि बिना उद्धरण के एकल उद्धरण सही ढंग से पार्स किए जाने चाहिए।

मैं JSON स्ट्रिंग के पार्स करने के लिए jquery`s jQuery.parseJSON फ़ंक्शन का उपयोग कर रहा हूं, लेकिन अभी भी पार्स त्रुटि हो रही है जब json_encode के साथ तैयार किए गए डेटा में एक ही उद्धरण है।

क्या यह मेरे कार्यान्वयन में एक गलती हो सकती है जो इस तरह दिखाई देती है (PHP - सर्वर साइड):

$data = array();

$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);

$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);

$jsonString = "[" . implode(", ", $data) . "]";

अंतिम चरण यह है कि मैं JSON एन्कोडेड स्ट्रिंग को JS वैरिएबल में संग्रहीत करता हूं:

<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>

यदि मैं "" के बजाय "" का उपयोग करता हूं तो यह अभी भी एक त्रुटि फेंकता है।

उपाय:

केवल एक चीज जो मेरे लिए काम करती थी, वह थी सिंगल बिट्स JSON_HEX_APOS का उपयोग इस तरह से एकल उद्धरण में परिवर्तित करने के लिए:

json_encode($tmp, JSON_HEX_APOS);

क्या इस मुद्दे से निपटने का एक और तरीका है? क्या मेरा कोड गलत है या खराब लिखा गया है?

धन्यवाद


'<= $ मार्कर? ?> 'यह वैध जसन नहीं है। आस-पास के उद्धरणों को जावास्क्रिप्ट इंटरप्रेटर द्वारा "खाया जाता है", एक स्ट्रिंग छोड़ रहा है जो एक <के साथ शुरू होता है ... जो आप वास्तव में कोशिश करना चाहते थे वह इनमें से एक था: jQuery.parseJSON ('' <<? = $ मार्कर? "" '); jQuery.parseJSON ("\" <? = $ मार्कर ?; \ ""); युक्ति के अनुसार, जसन स्ट्रिंग्स को दोहरे उद्धरण चिह्नों का उपयोग करना चाहिए, लेकिन जावास्क्रिप्ट का ध्यान नहीं है, इसलिए, आपके पास या तो एकल-उद्धरण जावास्क्रिप्ट स्ट्रिंग है, या एक दोहरे उद्धरण है, लेकिन यदि आप बाद वाले का उपयोग करते हैं, तो आपको उन सभी से बचना होगा स्ट्रिंग के अंदर दोहरे उद्धरण चिह्नों का उपयोग।
क्रिस कॉगडन

3

जब आप किसी क्वेरी में एकल उद्धरण भेज रहे हैं

empid = " T'via"
empid =escape(empid)

जब आप एक उद्धरण सहित मूल्य प्राप्त करते हैं

var xxx  = request.QueryString("empid")
xxx= unscape(xxx)

यदि आप उस मूल्य को खोजना / सम्मिलित करना चाहते हैं जिसमें एक क्वेरी में एक ही उद्धरण शामिल है xxx=Replace(empid,"'","''")


1
लेकिन एक JSON स्ट्रिंग के हिस्से के रूप में इसे पास करते समय एक भी उद्धरण से बचने की कोई आवश्यकता नहीं है ...
जस्टिन एथियर

2

PHP के मूल का उपयोग करते हुए जावास्क्रिप्ट स्क्रिप्ट-ब्लॉक को आउटपुट करने के लिए CakePHP का उपयोग करके एक समान समस्या का सामना करना पड़ रहा है json_encode$contractorCompaniesऐसे मान होते हैं जिनमें एकल उद्धरण चिह्न होते हैं और जैसा कि ऊपर बताया गया है और उम्मीद की जा रही json_encode($contractorCompanies)है कि वे इससे बच नहीं सकते क्योंकि इसका वैध JSON है।

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>

JSON एन्कोडेड स्ट्रिंग के चारों ओर Addlashes () जोड़कर आप तब ब्राउज़र से सही जावास्क्रिप्ट को गूंजने के लिए केक / PHP की अनुमति देने वाले उद्धरण चिह्नों से बच सकते हैं। जेएस त्रुटियों गायब हो जाते हैं।

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>

1

मैं एक XHR अनुरोध से एक JSON ऑब्जेक्ट को HTML5 डेटा- * विशेषता में सहेजने की कोशिश कर रहा था। मैंने उपरोक्त कई समाधानों को बिना किसी सफलता के आजमाया।

मैं आखिरकार क्या कर रहा हूँ स्ट्रिंग के बाद रीगेक्स का उपयोग करके 'कोड के साथ एकल उद्धरण की जगह ले रहा था &#39;() विधि निम्न तरीके से कॉल करें:

var productToString = JSON.stringify(productObject);
var quoteReplaced = productToString.replace(/'/g, "&#39;");
var anchor = '<a data-product=\'' + quoteReplaced + '\' href=\'#\'>' + productObject.name + '</a>';
// Here you can use the "anchor" variable to update your DOM element.

0

दिलचस्प। आप सर्वर के अंत में अपना JSON कैसे उत्पन्न कर रहे हैं? क्या आप लाइब्रेरी फंक्शन (जैसे json_encodePHP में) का उपयोग कर रहे हैं, या आप हाथ से JSON स्ट्रिंग बना रहे हैं?

केवल एक चीज जो मेरा ध्यान पकड़ती है वह है पलायन एपोस्ट्रोफ ( \')। यह देखते हुए कि आप दोहरे उद्धरण चिह्नों का उपयोग कर रहे हैं, जैसा कि आपको वास्तव में करना चाहिए, एकल उद्धरणों से बचने की कोई आवश्यकता नहीं है। अगर मैं वास्तव में आपके jQuery त्रुटि का कारण हूं, तो मैं यह जांच नहीं कर सकता कि मैंने अभी तक 1.4.1 संस्करण में अपडेट नहीं किया है।


मैं JSON ऑब्जेक्ट जनरेट करने के लिए PHP में एक लाइब्रेरी का उपयोग करता हूं - उस लिखने में चूक हुई। यह बात बताने के लिए धन्यवाद।
एरिक Eरपंजक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.