864 Stimmen

Speichern von UTF-8-Texten mit json.dumps als UTF-8, nicht als \u Escape-Sequenz

Beispielcode (in einem REPL):

import json
json_string = json.dumps(" ")
print(json_string)

Ausgabe:

"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"

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

Gibt es eine Möglichkeit, Objekte in UTF-8 JSON-Strings zu serialisieren (anstatt \uXXXX)?

1222voto

Martijn Pieters Punkte 953257

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

>>> json_string = json.dumps(" ", ensure_ascii=False).encode('utf8')
>>> json_string
b'"\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94"'
>>> print(json_string.decode())
" "

Wenn Sie in eine Datei schreiben, verwenden Sie einfach json.dump() und überlassen Sie es dem Dateiobjekt, die Kodierung vorzunehmen:

with open('filename', 'w', encoding='utf8') as json_file:
    json.dump(" ", json_file, ensure_ascii=False)

Vorsichtsmaßnahmen für Python 2

Für Python 2 gibt es einige zusätzliche Punkte zu beachten. Wenn Sie dies in eine Datei schreiben, können Sie anstelle von open() io.open() verwenden, um ein Dateiobjekt zu erstellen, das Unicode-Werte für Sie kodiert, während Sie schreiben. Verwenden Sie dann json.dump() zum Schreiben in diese Datei:

with io.open('filename', 'w', encoding='utf8') as json_file:
    json.dump(u" ", json_file, ensure_ascii=False)

Beachten Sie, dass es einen Fehler im json Modul gibt, bei dem das Flag ensure_ascii=False eine Mischung von unicode und str Objekten erzeugen kann. Die Workaround-Lösung für Python 2 lautet dann:

with io.open('filename', 'w', encoding='utf8') as json_file:
    data = json.dumps(u" ", ensure_ascii=False)
    # unicode(data) dekodiert data automatisch in Unicode, wenn es sich um str handelt
    json_file.write(unicode(data))

In Python 2, wenn Sie Byte-Strings (Typ str), codiert in UTF-8, verwenden, stellen Sie sicher, dass Sie auch das Schlüsselwort encoding setzen:

>>> 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']

147voto

Hiep Tran Punkte 3522

Zum Schreiben in eine Datei

import codecs
import json

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

Zum Drucken auf die Standardausgabe

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

31voto

monitorius Punkte 3096

Dies ist die falsche Antwort, aber es ist trotzdem nützlich zu verstehen, warum sie falsch ist. Siehe Kommentare.

Verwende unicode-escape:

>>> d = {1: " ", 2: u" "}
>>> json_str = json.dumps(d).decode('unicode-escape').encode('utf8')
>>> print json_str
{"1": " ", "2": " "}

30voto

Jonathan Ray Punkte 529

Pieters' Python 2 Workaround scheitert an einem Grenzfall:

d = {u'Schlüsselwort': u'Schlechte Kreditkarten'}
with io.open('dateiname', 'w', encoding='utf8') as json_datei:
    daten = json.dumps(d, ensure_ascii=False).decode('utf8')
    try:
        json_datei.write(data)
    except TypeError:
        # Dekodieren der Daten zuerst in Unicode
        json_datei.write(data.decode('utf8'))

UnicodeEncodeError: 'ascii' codec kann Zeichen u'\xe7' in Position 25 nicht codieren: Ordinal nicht im Bereich von 128

Es stürzte auf den .decode('utf8') Teil von Zeile 3 ab. Ich habe das Problem behoben, indem ich das Programm viel einfacher gemacht habe, indem ich diesen Schritt sowie die Sonderbehandlung von ASCII vermieden habe:

with io.open('dateiname', 'w', encoding='utf8') as json_datei:
  daten = json.dumps(d, ensure_ascii=False, encoding='utf8')
  json_datei.write(unicode(data))

cat dateiname
{"Schlüsselwort": "Schlechte Kreditkarten"}

30voto

Nik Punkte 8316

Ab Python 3.7 funktioniert der folgende Code einwandfrei:

from json import dumps
result = {"symbol": "ƒ"}
json_string = dumps(result, sort_keys=True, indent=2, ensure_ascii=False)
print(json_string)

Ausgabe:

{"symbol": "ƒ"}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X