JSON में सिंगल बनाम डबल कोट्स


107

मेरा कोड:

import simplejson as json

s = "{'username':'dfdsfdsf'}" #1
#s = '{"username":"dfdsfdsf"}' #2
j = json.loads(s)

#1 परिभाषा गलत है

#2 परिभाषा सही है

मैंने सुना है कि पायथन में एकल और डबल उद्धरण विनिमेय हो सकता है। क्या कोई मुझे यह समझा सकता है?

जवाबों:


169

JSON सिंटैक्स Python सिंटैक्स नहीं है। JSON को इसके तारों के लिए दोहरे उद्धरण चिह्नों की आवश्यकता है।


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

6
इस पुष्टि के लिए धन्यवाद। जाहिरा तौर पर मैं केवल एक आयात कर रहा हूँ str(dict), और यह नहीं चाहता eval। एक साधारण .replace("'", '"')को चाल चलनी चाहिए।
isaaclw

8
और मैंने भी जल्द ही बोल दिया। जाहिरा तौर पर यह उससे अधिक जटिल है।
isaaclw

6
यदि आपको चारों ओर दोहरे उद्धरण चिह्नों का उपयोग करने की आवश्यकता है, तो आप इसमें json.dumps(..)दो बार कॉल कर सकते हैं : import json; d = dict(tags=["dog", "cat", "mouse"]); print json.dumps(json.dumps(d))जो देता है:"{\"tags\": [\"dog\", \"cat\", \"mouse\"]}"
rprasad

124

आप उपयोग कर सकते हैं ast.literal_eval()

>>> import ast
>>> s = "{'username':'dfdsfdsf'}"
>>> ast.literal_eval(s)
{'username': 'dfdsfdsf'}

9
मुझे यह उत्तर सबसे अच्छा लगता है: आपके पास अक्सर कोई विकल्प नहीं होता है: यदि कोई आपको एकल उद्धरण देता है, तो आपको एकल उद्धरण मिला है। या तो json.loads को एक अतिरिक्त तर्क की आवश्यकता है, या आपको इसका उपयोग करना चाहिए। वैश्विक स्तर पर "" "एक आपदा है, जैसे कि आने वाला डेटा क्या है:{ 'a' : 'this "string" really isn\'t!!!!' }
मार्क जेरोलिमेटोस

@ मर्क, इस विधि को नेस्टेड कोट्स के साथ एक पेचीदा स्थिति में अनुकूलित किया जा सकता है "{'link':'<a href="mylink">http://my.com</a>'}"? इस स्थिति में, ast.literal_evalसिंटैक्स त्रुटि
alancalvitti

1
यह मेरे लिए एक सुरक्षा जोखिम जैसा लगता है।
जैक्सनहेनचेन

2
यह प्रश्न का उत्तर कैसे देता है? यह JSON में एकल बनाम दोहरे उद्धरण के साथ क्या करना है? यह अद्भुत दृष्टिकोण आपको एक स्ट्रिंग से एक पायथन तानाशाह को लोड करने की अनुमति दे सकता है, लेकिन ओपी में मुख्य मुद्दा यह है कि स्ट्रिंग # 1 वैध JSON नहीं है जबकि स्ट्रिंग # 2 है।
jschultz410

43

आप JSON को दोहरे उद्धरण के साथ डंप कर सकते हैं:

import json

# mixing single and double quotes
data = {'jsonKey': 'jsonValue',"title": "hello world"}

# get string with all double quotes
json_string = json.dumps(data) 

12
यह गलत तरीका है। आप JSON पर अजगर डेटा संरचनाओं को क्रमबद्ध कर रहे हैं; मूल प्रश्न JSON को अजगर डेटा स्ट्रक्चर्स के बारे में बताने के बारे में है।
tedder42

5
विचार यह होगा कि अजगर को json.dumps के साथ json में अनुक्रमित किया जाए, फिर जब वह स्ट्रॉग रूप में हो, उस पर json.loads को कॉल करें।
२१

3
आप यहाँ समझने से चूक गए। अगर आप json स्ट्रिंग लोड करना चाहते हैं, तो इसे डबल कोट करना होगा। आप जो कर रहे हैं, वह अभी भी डस रहा है, न कि जॉन स्ट्रिंग।
लेगिटमे

12

खराब जोंस सिंटैक्स की समस्या को हल करने के लिए डेमज़ोन भी एक अच्छा पैकेज है:

pip install demjson

उपयोग:

from demjson import decode
bad_json = "{'username':'dfdsfdsf'}"
python_dict = decode(bad_json)

संपादित करें:

demjson.decodeक्षतिग्रस्त json के लिए एक महान उपकरण है, लेकिन जब आप json डेटा के बड़े amourt के साथ काम कर रहे हैं ast.literal_evalतो एक बेहतर मैच और बहुत तेज़ है।


4
demjson.decodeक्षतिग्रस्त जोंस के लिए एक महान उपकरण है - लेकिन दसियों या हजारों हज़ारों पैकेट वाले कार्यों के लिए, ast.literal_evalबहुत तेज़ है। नहीं कहने के लिए demjsonयह जगह नहीं है: मैं इसे तेजी से विफल होने की स्थिति में फॉलबैक के रूप में उपयोग करता हूं।
mjwunderlich

1
वास्तव में demjson एक बहुत बेहतर काम किया है, बजाय ast.literal_eval और json.loads के खिलाफ परीक्षण करने के लिए
Marware

4

उदाहरण के लिए, अब तक दिए गए उत्तरों के साथ दो मुद्दे, एक ऐसी गैर-मानक JSON को धारा देता है। क्योंकि तब किसी को आने वाली स्ट्रिंग (एक अजगर शब्दकोश नहीं) की व्याख्या करनी पड़ सकती है।

अंक 1 - demjson: पायथन 3.7 के साथ। + और कॉन्डा का उपयोग करते हुए मैं डेमेजॉन को स्थापित करने में सक्षम नहीं था, क्योंकि यह वर्तमान में पायथन> 3.5 का समर्थन नहीं करता है। इसलिए मुझे सरल साधनों के साथ समाधान की आवश्यकता है, उदाहरण के लिए astऔर / या json.dumps

अंक 2 - astऔर json.dumps: यदि एक JSON दोनों एक ही उद्धृत है और कम से कम एक मान में एक स्ट्रिंग है, जिसमें बदले में एकल उद्धरण शामिल हैं, तो एकमात्र सरल अभी तक व्यावहारिक समाधान जो मैंने पाया है दोनों को लागू करना है:

निम्नलिखित उदाहरण में हम मानते हैं lineकि आने वाली JSON स्ट्रिंग ऑब्जेक्ट है:

>>> line = str({'abc':'008565','name':'xyz','description':'can control TV\'s and more'})

चरण 1: आने वाली स्ट्रिंग को शब्दकोश में परिवर्तित करें ast.literal_eval()
चरण 2 का उपयोग करें : json.dumpsइसे कुंजियों और मूल्यों के विश्वसनीय रूपांतरण के लिए लागू करें, लेकिन मूल्यों की सामग्री को छूने के बिना :

>>> import ast
>>> import json
>>> print(json.dumps(ast.literal_eval(line)))
{"abc": "008565", "name": "xyz", "description": "can control TV's and more"}

json.dumpsअकेले काम नहीं करेगा क्योंकि यह JSON की व्याख्या नहीं करता है, लेकिन केवल स्ट्रिंग देखता है। इसके लिए समान ast.literal_eval(): हालाँकि यह JSON (डिक्शनरी) की सही व्याख्या करता है, लेकिन यह वह नहीं है जो हमें चाहिए।



2

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


यदि JSON तार में से एक में @Jiaaro द्वारा इंगित किया गया एक एकल उद्धरण शामिल है, तो नीचे विफल हो सकता है। प्रयोग नहीं करें। काम नहीं करने के उदाहरण के रूप में यहां छोड़ दिया।

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

a = json.loads('very_long_json_string_pasted_here')

यदि यह एकल उद्धरणों का भी उपयोग करता है, तो यह अन्यथा टूट सकता है।


2
यह सच नहीं है कि एक जॉगन स्ट्रिंग में एक भी उद्धरण नहीं हैं। यह एक विशिष्ट मामले में सच हो सकता है, लेकिन आप इस पर भरोसा नहीं कर सकते। उदाहरण के लिए, यह वैध {"key": "value 'with' single quotes"}
जसन है

2

यह वास्तव में eval फ़ंक्शन का उपयोग करके मेरी समस्या को हल करता है।

single_quoted_dict_in_string = "{'key':'value', 'key2': 'value2'}"
desired_double_quoted_dict = eval(single_quoted_dict_in_string)
# Go ahead, now you can convert it into json easily
print(desired_double_quoted_dict)

यह बहुत ही खराब उदाहरण है। क्या होगा अगर किसी को पता चलता है कि आप json पर eval का उपयोग कर रहे हैं और एक विकृत json कोड को भेजता है जिसका मूल्यांकन eval द्वारा किया जाता है?
१-२:

1

मैं हाल ही में एक ऐसी ही समस्या के खिलाफ आया था, और विश्वास है कि मेरा समाधान आपके लिए भी काम करेगा। मेरे पास एक टेक्स्ट फ़ाइल थी जिसमें फॉर्म में वस्तुओं की एक सूची थी:

["first item", 'the "Second" item', "thi'rd", 'some \\"hellish\\" \'quoted" item']

मैं ऊपर एक अजगर सूची में पार्स करना चाहता था, लेकिन मैं इनपुट पर भरोसा नहीं कर सकता था () के रूप में eval () पर उत्सुक नहीं था। मैंने पहले JSON का उपयोग करने की कोशिश की, लेकिन यह केवल दोहरे उद्धृत आइटम को स्वीकार करता है, इसलिए मैंने इस विशिष्ट मामले के लिए अपना स्वयं का बहुत ही सरल लेख लिखा है (बस अपने "स्ट्रिंगटॉप" में प्लग करें और आपको आउटपुट सूची के रूप में मिलेगा: 'आइटम')

#This lexer takes a JSON-like 'array' string and converts single-quoted array items into escaped double-quoted items,
#then puts the 'array' into a python list
#Issues such as  ["item 1", '","item 2 including those double quotes":"', "item 3"] are resolved with this lexer
items = []      #List of lexed items
item = ""       #Current item container
dq = True       #Double-quotes active (False->single quotes active)
bs = 0          #backslash counter
in_item = False #True if currently lexing an item within the quotes (False if outside the quotes; ie comma and whitespace)
for c in stringtoparse[1:-1]:   #Assuming encasement by brackets
    if c=="\\": #if there are backslashes, count them! Odd numbers escape the quotes...
        bs = bs + 1
        continue                    
    if (dq and c=='"') or (not dq and c=="'"):  #quote matched at start/end of an item
        if bs & 1==1:   #if escaped quote, ignore as it must be part of the item
            continue
        else:   #not escaped quote - toggle in_item
            in_item = not in_item
            if item!="":            #if item not empty, we must be at the end
                items += [item]     #so add it to the list of items
                item = ""           #and reset for the next item
            continue                
    if not in_item: #toggle of single/double quotes to enclose items
        if dq and c=="'":
            dq = False
            in_item = True
        elif not dq and c=='"':
            dq = True
            in_item = True
        continue
    if in_item: #character is part of an item, append it to the item
        if not dq and c=='"':           #if we are using single quotes
            item += bs * "\\" + "\""    #escape double quotes for JSON
        else:
            item += bs * "\\" + c
        bs = 0
        continue

उम्मीद है कि यह किसी के लिए उपयोगी है। का आनंद लें!


यह आपको क्या प्रदान करता है जो आपको docs.python.org/2/library/ast.html#ast.literal_eval से नहीं मिलता है ?
चार्ल्स डफी

0
import ast 
answer = subprocess.check_output(PYTHON_ + command, shell=True).strip()
    print(ast.literal_eval(answer.decode(UTF_)))

मेरे लिये कार्य करता है


-4
import json
data = json.dumps(list)
print(data)

उपरोक्त कोड स्निपेट को काम करना चाहिए।


2
यह कुछ उपयोगी हो सकता है, लेकिन यह उस प्रश्न का उत्तर नहीं देता है जो पूछा गया था। समस्या स्ट्रिंग से शुरू होती है, सूची से नहीं।
राहेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.