948 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)?

1332voto

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

160voto

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))

41voto

sivi Punkte 9816

Danke für die ursprüngliche Antwort hier. Mit Python 3 war die folgende Codezeile in Ordnung:

print(json.dumps(result_dict,ensure_ascii=False))

Überlegen Sie, nicht zu viel Text im Code zu schreiben, wenn es nicht zwingend erforderlich ist.

Dies könnte für die Python-Konsole ausreichend sein. Um jedoch einen Server zu befriedigen, müssen Sie möglicherweise das Locale wie hier erklärt einstellen (wenn es sich um Apache 2 handelt) Einstellen von LANG und LC_ALL bei Verwendung von mod_wsgi

Installieren Sie im Grunde he_IL oder was auch immer Sprachlocale auf Ubuntu. Überprüfen Sie, ob es nicht installiert ist:

locale -a

Installieren Sie es, wobei XX Ihre Sprache ist:

sudo apt-get install language-pack-XX

Zum Beispiel:

sudo apt-get install language-pack-he

Fügen Sie den folgenden Text zu /etc/apache2/envvrs hinzu

export LANG='he_IL.UTF-8'
export LC_ALL='he_IL.UTF-8'

Dann sollten Sie hoffentlich keine Python-Fehler von Apache wie folgt erhalten:

print (js) UnicodeEncodeError: 'ascii' codec can't encode characters in position 41-45: ordinal not in range(128)

Versuchen Sie auch in Apache, UTF zur Standardcodierung zu machen, wie hier erklärt: Wie ändere ich die Standardcodierung auf UTF-8 für Apache

Tun Sie dies frühzeitig, da Apache-Fehler schwer zu debuggen sein können und Sie möglicherweise fälschlicherweise denken, dass sie von Python stammen, was in dieser Situation möglicherweise nicht der Fall ist.

33voto

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": "ƒ"}

32voto

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": " "}

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