Speichern von UTF-8-Texten in json.dumps als UTF8, nicht als Esc-Sequenz

Beispielcode:

>>> import json >>> json_string = json.dumps("ברי צקלה") >>> print json_string "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4" 

Das Problem: Es ist nicht lesbar. Meine (intelligenten) Benutzer möchten Textdateien mit JSON-Dumps verifizieren oder sogar bearbeiten. (und ich würde lieber nicht XML verwenden)

Gibt es eine Möglichkeit, Objekte in utf-8 json string zu serialisieren (anstelle von \ uXXXX)?

das hilft nicht:

 >>> output = json_string.decode('string-escape') "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4" 

das funktioniert, aber wenn irgendein Unterobjekt ein PythonUnicode und nicht UTF-8 ist, wird Müll ausgegeben:

 >>> #### ok: >>> s= json.dumps( "ברי צקלה", ensure_ascii=False) >>> print json.loads(s) ברי צקלה >>> #### NOT ok: >>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" } >>> print d {1: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 2: u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94'} >>> s = json.dumps( d, ensure_ascii=False, encoding='utf8') >>> print json.loads(s)['1'] ברי צקלה >>> print json.loads(s)['2'] ××¨× ×¦×§×× 

Solutions Collecting From Web of "Speichern von UTF-8-Texten in json.dumps als UTF8, nicht als Esc-Sequenz"

Verwenden Sie den Schalter ” ensure_ascii=False für ” json.dumps() , und codieren Sie den Wert manuell in UTF-8:

 >>> json_string = json.dumps(u"ברי צקלה", ensure_ascii=False).encode('utf8') >>> json_string '"\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94"' >>> print json_string "ברי צקלה" 

Wenn Sie dies in eine Datei schreiben, können Sie io.open() anstelle von open() , um ein io.open() zu erstellen, das während des Schreibens Unicode-Werte für Sie codiert. Verwenden json.dump() stattdessen json.dump() , um in diese Datei zu schreiben :

 with io.open('filename', 'w', encoding='utf8') as json_file: json.dump(u"ברי צקלה", json_file, ensure_ascii=False) 

In Python 3 ist das integrierte open() ein Alias ​​für io.open() . Beachten Sie, dass es im json Modul einen Fehler gibt, bei dem das ensure_ascii=False Flag eine Mischung aus unicode und str Objekten erzeugen kann. Die Problemumgehung für Python 2 ist dann:

 with io.open('filename', 'w', encoding='utf8') as json_file: data = json.dumps(u"ברי צקלה", ensure_ascii=False) # unicode(data) auto-decodes data to unicode if str json_file.write(unicode(data)) 

Wenn Sie Byte-Strings (Typ str in Python 2, bytes in Python 3) übergeben, die in UTF-8 codiert sind, stellen Sie sicher, dass Sie auch das Schlüsselwort encoding festlegen:

 >>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" } >>> d {1: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 2: u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'} >>> s=json.dumps(d, ensure_ascii=False, encoding='utf8') >>> s u'{"1": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4", "2": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"}' >>> json.loads(s)['1'] u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4' >>> json.loads(s)['2'] u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4' >>> print json.loads(s)['1'] ברי צקלה >>> print json.loads(s)['2'] ברי צקלה 

Beachten Sie, dass Ihr zweites Beispiel nicht gültig Unicode ist; Sie gaben ihm UTF-8 Bytes als Unicode-Literal, das würde nie funktionieren:

 >>> s = u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94' >>> print s ××¨× ×¦×§×× >>> print s.encode('latin1').decode('utf8') ברי צקלה 

Nur wenn ich diese Zeichenfolge nach Latin 1 codiert habe (deren Unicode-Codepunkte Eins-zu-Eins zu Bytes zuordnen), dekodieren Sie als UTF-8 die erwartete Ausgabe. Das hat nichts mit JSON zu tun und alles damit zu tun, dass du die falsche Eingabe verwendest. Das Ergebnis wird Mojibake genannt .

Wenn Sie diesen Unicode-Wert aus einem String-Literal erhalten haben, wurde er mit dem falschen Codec dekodiert. Es kann sein, dass Ihr Terminal falsch konfiguriert ist oder dass Ihr Texteditor Ihren Quellcode mit einem anderen Codec gespeichert hat als dem, zu dem Sie Python gesagt haben, dass er die Datei lesen soll. Oder Sie haben es aus einer Bibliothek bezogen, die den falschen Codec angewendet hat. Das alles hat nichts mit der JSON-Bibliothek zu tun .

einfach wie ein Kuchen

Um in eine Datei zu schreiben

 import codecs import json with codecs.open('your_file.txt', 'w', encoding='utf-8') as f: json.dump({"message":"xin chào việt nam"}, f, ensure_ascii=False) 

Um zu stdin zu drucken

 import codecs import json print(json.dumps({"message":"xin chào việt nam"}, ensure_ascii=False)) 

UPDATE: Das ist eine falsche Antwort, aber es ist immer noch nützlich zu verstehen, warum es falsch ist. Zeige Kommentare.

Wie wäre es mit unicode-escape ?

 >>> d = {1: "ברי צקלה", 2: u"ברי צקלה"} >>> json_str = json.dumps(d).decode('unicode-escape').encode('utf8') >>> print json_str {"1": "ברי צקלה", "2": "ברי צקלה"} 

Die Umgehung von Python 2 von Peters schlägt bei einem Edge Case fehl:

 d = {u'keyword': u'bad credit \xe7redit cards'} with io.open('filename', 'w', encoding='utf8') as json_file: data = json.dumps(d, ensure_ascii=False).decode('utf8') try: json_file.write(data) except TypeError: # Decode data to Unicode first json_file.write(data.decode('utf8')) UnicodeEncodeError: 'ascii' codec can't encode character u'\xe7' in position 25: ordinal not in range(128) 

Es stürzte auf den .decode (‘utf8’) -Teil von Zeile 3. Ich reparierte das Problem, indem ich das Programm viel einfacher machte, indem ich diesen Schritt sowie die spezielle Hülle von ascii vermied:

 with io.open('filename', 'w', encoding='utf8') as json_file: data = json.dumps(d, ensure_ascii=False, encoding='utf8') json_file.write(unicode(data)) cat filename {"keyword": "bad credit çredit cards"} 

Das folgende ist mein Verständnis var Lesung Antwort oben und google.

 # coding:utf-8 r""" @update: 2017-01-09 14:44:39 @explain: str, unicode, bytes in python2to3 #python2 UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 7: ordinal not in range(128) #1.reload #importlib,sys #importlib.reload(sys) #sys.setdefaultencoding('utf-8') #python3 don't have this attribute. #not suggest even in python2 #see:http://stackoverflow.com/questions/3828723/why-should-we-not-use-sys-setdefaultencodingutf-8-in-a-py-script #2.overwrite /usr/lib/python2.7/sitecustomize.py or (sitecustomize.py and PYTHONPATH=".:$PYTHONPATH" python) #too complex #3.control by your own (best) #==> all string must be unicode like python3 (u'xx'|b'xx'.encode('utf-8')) (unicode 's disappeared in python3) #see: http://blog.ernest.me/post/python-setdefaultencoding-unicode-bytes #how to Saving utf-8 texts in json.dumps as UTF8, not as \u escape sequence #http://stackoverflow.com/questions/18337407/saving-utf-8-texts-in-json-dumps-as-utf8-not-as-u-escape-sequence """ from __future__ import print_function import json a = {"b": u"中文"} # add u for python2 compatibility print('%r' % a) print('%r' % json.dumps(a)) print('%r' % (json.dumps(a).encode('utf8'))) a = {"b": u"中文"} print('%r' % json.dumps(a, ensure_ascii=False)) print('%r' % (json.dumps(a, ensure_ascii=False).encode('utf8'))) # print(a.encode('utf8')) #AttributeError: 'dict' object has no attribute 'encode' print('') # python2:bytes=str; python3:bytes b = a['b'].encode('utf-8') print('%r' % b) print('%r' % b.decode("utf-8")) print('') # python2:unicode; python3:str=unicode c = b.decode('utf-8') print('%r' % c) print('%r' % c.encode('utf-8')) """ #python2 {'b': u'\u4e2d\u6587'} '{"b": "\\u4e2d\\u6587"}' '{"b": "\\u4e2d\\u6587"}' u'{"b": "\u4e2d\u6587"}' '{"b": "\xe4\xb8\xad\xe6\x96\x87"}' '\xe4\xb8\xad\xe6\x96\x87' u'\u4e2d\u6587' u'\u4e2d\u6587' '\xe4\xb8\xad\xe6\x96\x87' #python3 {'b': '中文'} '{"b": "\\u4e2d\\u6587"}' b'{"b": "\\u4e2d\\u6587"}' '{"b": "中文"}' b'{"b": "\xe4\xb8\xad\xe6\x96\x87"}' b'\xe4\xb8\xad\xe6\x96\x87' '中文' '中文' b'\xe4\xb8\xad\xe6\x96\x87' """ 

Hier ist meine Lösung mit json.dump ():

 def jsonWrite(p, pyobj, ensure_ascii=False, encoding=SYSTEM_ENCODING, **kwargs): with codecs.open(p, 'wb', 'utf_8') as fileobj: json.dump(pyobj, fileobj, ensure_ascii=ensure_ascii,encoding=encoding, **kwargs) 

wo SYSTEM_ENCODING gesetzt ist auf:

 locale.setlocale(locale.LC_ALL, '') SYSTEM_ENCODING = locale.getlocale()[1] 

Verwenden Sie möglichst Codecs,

 with codecs.open('file_path', 'a+', 'utf-8') as fp: fp.write(json.dumps(res, ensure_ascii=False)) 

Die Verwendung von use_ascii = False in json.dumps ist die richtige Richtung, um dieses Problem zu lösen, wie Martijn darauf hingewiesen hat. Dies kann jedoch eine Ausnahme auslösen:

 UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 1: ordinal not in range(128) 

Sie benötigen zusätzliche Einstellungen in site.py oder sitecustomize.py, um Ihre sys.getdefaultencoding () – Einstellung korrekt zu setzen. site.py befindet sich unter lib / python2.7 / und sitecustomize.py befindet sich unter lib / python2.7 / site-packages.

Wenn Sie site.py unter def setencoding () verwenden wollen: ändern Sie das erste if 0: in if 1: so dass Python das Gebietsschema Ihres Betriebssystems verwendet.

Wenn Sie es vorziehen, sitecustomize.py zu verwenden, das möglicherweise nicht vorhanden ist, wenn Sie es nicht erstellt haben. setze einfach diese Zeilen:

 import sys reload(sys) sys.setdefaultencoding('utf-8') 

Dann können Sie eine chinesische json Ausgabe im utf-8 Format machen, wie zum Beispiel:

 name = {"last_name": u"王"} json.dumps(name, ensure_ascii=False) 

Sie erhalten eine utf-8-codierte Zeichenfolge und keine entweichte json-Zeichenfolge.

So überprüfen Sie Ihre Standardcodierung:

 print sys.getdefaultencoding() 

Sie sollten “utf-8” oder “UTF-8” abrufen, um Ihre Einstellungen für site.py oder sitecustomize.py zu überprüfen.

Bitte beachten Sie, dass Sie sys.setdefaultencoding (“utf-8”) nicht an der interaktiven Python-Konsole ausführen können.