JSON'da tek ve çift tırnak


109

Kodum:

import simplejson as json

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

#1 tanım yanlış

#2 tanım doğru

Python'da tek ve çift alıntının birbiriyle değiştirilebileceğini duydum . Bunu bana kimse açıklayabilir mi?

Yanıtlar:


170

JSON sözdizimi , Python sözdizimi değildir. JSON, dizeleri için çift tırnak gerektirir.


2
ama birincisi JSON'da tek alıntı, kafam karıştı. Biri derlemeyi geçebilir ama ikincisi geçemez.
Bin Chen

6
Bu onay için teşekkür ederim. Görünüşe göre ithal eden tek kişi benim str(dict)ve bunu yapmak istemiyor eval. Basit bir .replace("'", '"')hile yapmalı.
isaaclw

8
Ve çok erken konuştum. Görünüşe göre bundan daha karmaşık.
isaaclw

6
Her yerde çift tırnak kullanmanız gerekiyorsa, şu şekilde json.dumps(..)iki kez arayabilirsiniz import json; d = dict(tags=["dog", "cat", "mouse"]); print json.dumps(json.dumps(d)):"{\"tags\": [\"dog\", \"cat\", \"mouse\"]}"
rprasad

125

kullanabilirsiniz ast.literal_eval()

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

9
Bu cevabı en çok beğendim: çoğu zaman bir seçeneğin yok: biri sana tek alıntılar verirse, tek tırnak alırsın. Ya json.loads fazladan bir argümana ihtiyaç duyar ya da bunu kullanmalısınız. Küresel olarak "" "yerine { 'a' : 'this "string" really isn\'t!!!!' }
geçmek

@Mark, bu yöntem iç içe geçmiş alıntılarla daha zor bir duruma uyarlanabilir "{'link':'<a href="mylink">http://my.com</a>'}"mi? Bu durumda, ast.literal_evalsözdizimi hatası atar
alancalvitti

1
Bu benim için bir güvenlik riski gibi görünüyor.
JacksonHaenchen

2
Bu soruya nasıl cevap veriyor? Bunun JSON'daki tek ve çift tırnak işaretleri ile ne ilgisi var? Bu ast yaklaşım, bir dizeden bir Python diktesini yüklemenize izin verebilir, ancak OP'nin sahip olduğu ana sorun, dizge # 1'in geçerli JSON olmaması ve dizge # 2'nin geçerli olmasıdır.
jschultz410

44

JSON'u çift tırnakla dökümünü şu şekilde yapabilirsiniz:

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
bu yanlış yöne gidiyor. python veri yapılarını JSON'a serileştiriyorsunuz; asıl soru JSON'u python veri yapılarına serileştirmeden çıkarmakla ilgilidir.
tedder42

5
Buradaki fikir, python'u json.dumps ile json'a serileştirmek, ardından str formundayken üzerinde json.loads'ı çağırmak olacaktır.
2016

3
Burada anlamayı özledin. Json dizesini yüklemek istiyorsanız, çift tırnak olması gerekir. Yaptığınız şey hala json dökümü, json dizesi değil.
LegitMe

12

demjson ayrıca kötü json sözdizimi sorununu çözmek için iyi bir pakettir:

pip install demjson

Kullanım:

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

Düzenle:

demjson.decodehasarlı json için harika bir araçtır, ancak büyük miktarda json verileriyle uğraşırken ast.literal_evaldaha iyi bir eşleşme ve çok daha hızlıdır.


4
demjson.decodehasarlı json için harika bir araçtır - ancak onlarca veya yüz binlerce json paketini içeren görevler ast.literal_evaliçin çok daha hızlıdır. Onun yeri olmadığını söylemem demjson: Daha hızlı yöntemlerin başarısız olması durumunda onu geri dönüş olarak kullanıyorum.
mjwunderlich

1
Aslında demjson ast.literal_eval ve json.loads'a karşı test etmek yerine çok daha iyi çalıştı
Marware

5

Şu ana kadar verilen yanıtlarla ilgili iki sorun; örneğin, biri standart olmayan JSON'u yayınlarsa. Çünkü o zaman kişi gelen bir dizeyi yorumlamak zorunda kalabilir (bir python sözlüğü değil).

Sorun 1 - demjson: Python 3.7. + İle ve conda kullanarak demjson'u yükleyemedim, çünkü açıkça Python> 3.5'i desteklemiyor. Bu yüzden daha basit araçlara sahip bir çözüme ihtiyacım var, örneğin astve / veya json.dumps.

Sayı 2 - ast&json.dumps : Bir JSON hem tek tırnaklıysa hem de en az bir değerde bir dize içeriyorsa, bu da tek tırnak işareti içeriyorsa, bulduğum tek basit ama pratik çözüm her ikisini de uygulamaktır:

Aşağıdaki örnekte line, gelen JSON dize nesnesi olduğunu varsayıyoruz :

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

Adım 1: Gelen dizeyi ast.literal_eval()
2. Adım'ı kullanarak bir sözlüğe json.dumpsdönüştürün: Anahtarların ve değerlerin güvenilir bir şekilde dönüştürülmesi için buna başvurun, ancak değerlerin içeriğine dokunmadan :

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

json.dumpsJSON'u yorumlamadığı için yalnızca dizeyi gördüğü için işi tek başına yapmaz. Benzer ast.literal_eval(): JSON'u (sözlük) doğru yorumlasa da, ihtiyacımız olanı dönüştürmez.


3

Bunu şu şekilde düzeltebilirsiniz:

s = "{'username':'dfdsfdsf'}"
j = eval(s)

Enjeksiyon saldırılarından kaçınmak için eval yerine ast.literal_eval kullanın
Simon Kingaby

2

Söylendiği gibi, JSON, Python sözdizimi değildir. JSON'da çift tırnak kullanmanız gerekir. Oluşturucusu, programcıların bilişsel aşırı yüklenmesini kolaylaştırmak için izin verilebilir sözdiziminin katı alt kümelerini kullanmasıyla (in-) ünlüdür.


JSON dizelerinden birinin kendisi @ Jiaaro'nun belirttiği gibi tek bir alıntı içeriyorsa, aşağıda başarısız olabilir. KULLANMAYIN. Neyin işe yaramadığına dair bir örnek olarak burada bırakıldı.

Öyle gerçekten yararlı bir JSON dizesinde tek tırnak olduğunu bilmek. Diyelim ki, onu bir tarayıcı konsolundan kopyalayıp yapıştırdınız. Sonra yazabilirsin

a = json.loads('very_long_json_string_pasted_here')

Aksi takdirde, tek tırnak kullanması halinde bu bozulabilir.


2
bir json dizesinde tek tırnak olmadığı doğru değildir. Bu belirli bir durumda doğru olabilir, ancak buna güvenemezsiniz. örneğin, bu geçerli bir json:{"key": "value 'with' single quotes"}
Jiaaro

2

Eval işlevini kullanarak sorunumu gerçekten çözdü.

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)

Bu çok kötü bir örnek. Ya birisi eval üzerinde json kullandığınızı anlarsa ve daha sonra eval tarafından değerlendirilen kod içeren hatalı biçimlendirilmiş bir json gönderirse?
Metonimi

1

Geçenlerde çok benzer bir sorunla karşılaştım ve çözümümün sizin için de işe yarayacağına inanıyorum. Formdaki öğelerin listesini içeren bir metin dosyam vardı:

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

Yukarıdakileri bir python listesine ayrıştırmak istedim, ancak girdiye güvenemediğim için eval () 'a istekli değildim. İlk olarak JSON kullanmayı denedim, ancak sadece çift tırnaklı öğeleri kabul ediyor, bu yüzden bu özel durum için kendi çok basit sözlüğümü yazdım (sadece kendi "stringtoparse" nizi ekleyin ve çıktı listesi olarak şunu alacaksınız: 'öğeler')

#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

Umarım birisi için yararlıdır. Zevk almak!



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

Benim için çalışıyor


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

Yukarıdaki kod parçacığı çalışmalıdır.


2
Yararlı bir şey yapabilir, ancak sorulan soruyu yanıtlamaz. Sorun bir listeyle değil, bir dizeyle başlar.
Rachel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.