JSONの単一引用符と二重引用符


107

私のコード:

import simplejson as json

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

#1 定義が間違っている

#2 定義は正しい

Pythonではそのシングルダブルが引用符引用符は交換可能である。誰かがこれを私に説明できますか?

回答:


169

JSON構文はPython 構文ではありません。JSONでは、文字列に二重引用符が必要です。


2
しかし、最初の1つはJSONの単一引用符です。混乱しています。その1つはコンパイルを渡すことができますが、2つ目はできません。
Bin Chen

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!!!!' }
マーク・Gerolimatos

@Mark、このメソッドは、ネストされた引用符などのトリッキーな状況に適応でき"{'link':'<a href="mylink">http://my.com</a>'}"ますか?この場合、ast.literal_eval構文エラーをスローします
alancalvitti

1
これはセキュリティ上のリスクのようです。
JacksonHaenchen

2
これはどのように質問に答えますか?これは、JSONの単一引用符と二重引用符とどう関係しているのですか?このastアプローチでは、文字列からPython dictを読み込むことができますが、OPの主な問題は、文字列#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
これは間違った方向に進みます。Pythonデータ構造をJSONにシリアル化しています。元の質問は、JSONをpythonデータ構造に逆シリアル化することです。
tedder42 2015

5
アイデアは、json.dumpsを使用してpythonをjsonにシリアル化し、それがstrフォームにあるときにjson.loadsを呼び出すことです。
jheld

3
あなたはここで理解を逃しています。json文字列をロードする場合は、二重引用符で囲む必要があります。あなたがやっていることはまだjsonをダンプすることであり、json文字列ではありません。
LegitMe 2016

12

demjsonは、json構文の問題を解決するための優れたパッケージでもあります。

pip install demjson

使用法:

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

編集:

demjson.decode損傷したjsonには優れたツールですが、大量のjsonデータを処理する場合ast.literal_evalは、より適切に一致し、はるかに高速になります。


4
demjson.decode損傷したjsonには優れたツールですが、数万または数十万のjsonパケットを含むタスクの場合ast.literal_evalは、はるかに高速です。言うまでもありdemjsonませんが、高速なメソッドが失敗した場合のフォールバックとして使用します。
mjwunderlich 2016年

1
実際、demjsonは、ast.literal_evalとjson.loadsに対してテストするのではなく、はるかにうまく機能します
Marware

4

たとえば、1つがそのような非標準のJSONをストリーミングする場合、これまでに与えられた回答に関する2つの問題。それは、(Python辞書ではなく)入力文字列を解釈する必要があるためです。

問題1- demjson:Python 3.7。+でcondaを使用すると、現在のところpython> 3.5をサポートしていないため、demjsonをインストールできませんでした。したがって、たとえばast、および/またはより簡単な手段を備えたソリューションが必要json.dumpsです。

問題2- astjson.dumps:JSONが両方とも単一引用符で囲まれ、少なくとも1つの値に文字列が含まれ、次に単一引用符が含まれる場合、私が見つけた唯一のシンプルで実用的な解決策は両方を適用することです。

次の例で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.dumpsJSONを解釈せず、文字列のみを表示するため、単独では機能しません。同様にast.literal_eval():JSON(辞書)を正しく解釈しますが、必要なものは変換しません。


3

あなたはそれをそのように修正することができます:

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

インジェクション攻撃を回避するには、evalではなくast.literal_evalを使用してください
Simon Kingaby

2

前述のとおり、JSONはPythonの構文ではありません。JSONでは二重引用符を使用する必要があります。その作成者は、プログラマーの認知過負荷を緩和するために、許可された構文の厳密なサブセットを使用することで(非)有名です。


@Jiaaroによって指摘されたように、JSON文字列の1つ自体に単一引用符が含まれている場合、以下が失敗する可能性があります。使ってはいけません。機能しない例としてここに残しました。

JSON文字列に単一引用符がないことを知っていることは本当に役に立ちます。たとえば、ブラウザコンソールなどからコピーして貼り付けたとします。次に、単に入力することができます

a = json.loads('very_long_json_string_pasted_here')

単一引用符も使用している場合は、これが壊れる可能性があります。


2
json文字列に単一引用符がないことは真実ではありません。それは特定のケースでは当てはまるかもしれませんが、それに頼ることはできません。たとえば、これは有効なjsonです{"key": "value 'with' single quotes"}
。– Jiaaro

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によって評価されますか?
Metonymy

1

私は最近、非常に類似した問題に直面しました。私の解決策もあなたのために機能すると信じています。次の形式の項目のリストを含むテキストファイルがありました。

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

上記をpythonリストに解析したかったのですが、入力を信頼できなかったため、eval()には熱心ではありませんでした。最初にJSONを使用してみましたが、二重引用符で囲まれたアイテムしか受け入れないため、この特定のケース用に独自の非常にシンプルなレクサーを作成しました(独自の「stringtoparse」をプラグインするだけで、出力リストとして表示されます: 'items')

#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から得られないものは何ですか?
Charles Duffy

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
何か役立つことをするかもしれませんが、尋ねられた質問には答えません。問題はリストではなく文字列から始まります。
レイチェル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.