web-dev-qa-db-ja.com

Json.dumpが「strではなくユニコードでなければなりません」TypeErrorで失敗する

中国語と日本語(および他の言語)の文字が多数含まれているjsonファイルがあります。次のように_io.open_を使用して、python 2.7スクリプトにロードしています。

_with io.open('multiIdName.json', encoding="utf-8") as json_data:
    cards = json.load(json_data)
_

Jsonに新しいプロパティを追加します。すべて良いです。次に、別のファイルに書き戻そうとします。

_with io.open("testJson.json",'w',encoding="utf-8") as outfile:
        json.dump(cards, outfile, ensure_ascii=False)
_

それがエラー_TypeError: must be unicode, not str_を受け取るときです

私はoutfileをバイナリ(with io.open("testJson.json",'wb') as outfile:)として書き込もうとしましたが、最終的には次のようになりました:

_{"multiverseid": 262906, "name": "\u00e6\u00b8\u00b8\u00e9\u009a\u00bc\u00e7\u008b\u00ae\u00e9\u00b9\u00ab", "language": "Chinese Simplified"}
_

Ensure_asciiフラグと同様に、同じエンコーディングでそれを開いて書くだけで十分だと思いましたが、明らかにそうではありません。スクリプトを実行する前に、ファイルに存在する文字を\ uに変換せずに保持したいだけです。

17
IronWaffleMan

以下を試すことができますか?

with io.open("testJson.json",'w',encoding="utf-8") as outfile:
  outfile.write(unicode(json.dumps(cards, ensure_ascii=False)))
29
Yaron

このエラーの理由は、json.dumps in Python 2:

>>> json.dumps({'a': 'a'}, ensure_ascii=False)
'{"a": "a"}'
>>> json.dumps({'a': u'a'}, ensure_ascii=False)
u'{"a": "a"}'
>>> json.dumps({'a': 'ä'}, ensure_ascii=False)
'{"a": "\xc3\xa4"}'
>>> json.dumps({u'a': 'ä'}, ensure_ascii=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 250, in dumps
    sort_keys=sort_keys, **kw).encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 210, in encode
    return ''.join(chunks)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

これは、io.openencodingが設定されている場合、unicodeオブジェクト(それ自体が正しい)のみを受け入れ、問題が発生します。

戻り型は、辞書内のキーまたは値のタイプに完全に依存します(ensure_ascii=False、ただしstrは、ensure_ascii=True。誤って8ビット文字列を辞書に設定できる場合、needを設定する必要があるため、この戻り値の型を盲目的にunicodeに変換することはできませんエンコーディング、おそらくUTF-8:

>>> x = json.dumps(obj, ensure_ascii=False)
>>> if isinstance(x, str):
...     x = unicode(x, 'UTF-8')

thisの場合、json.dump開いているバイナリファイルに書き込む。ただし、結果のオブジェクトでもっと複雑なことをする必要がある場合は、おそらく上記のコードが必要です。


1つの解決策は、Python 3。

5
Antti Haapala

JSONモジュールはエンコードとデコードを処理するため、入力ファイルと出力ファイルをバイナリモードで簡単に開くことができます。 JSONモジュールはUTF-8エンコードを想定していますが、load()およびdump()メソッドのencoding属性を使用して変更できます。

with open('multiIdName.json', 'rb') as json_data:
    cards = json.load(json_data)

その後:

with open("testJson.json", 'wb') as outfile:
    json.dump(cards, outfile, ensure_ascii=False)

@Antti Haapalaのおかげで、Python 2.x JSONモジュールは、オブジェクトのコンテンツに応じてUnicodeまたはstrを提供します。

ioを使用して書き込む前に、結果がUnicodeであることを確認するために、センスチェックを追加する必要があります。

with io.open("testJson.json", 'w', encoding="utf-8") as outfile:
    my_json_str = json.dumps(my_obj, ensure_ascii=False)
    if isinstance(my_json_str, str):
        my_json_str = my_json_str.decode("utf-8")

    outfile.write(my_json_str)
3