Zapisywanie tekstów utf-8 za pomocą json.zrzuty jako UTF8, nie jako sekwencja ucieczki \u

Przykładowy kod:

>>> import json
>>> json_string = json.dumps("ברי צקלה")
>>> print(json_string)
"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"
Problem: nie jest czytelny dla człowieka. Moi (inteligentni) użytkownicy chcą zweryfikować lub nawet edytować pliki tekstowe za pomocą zrzutów JSON (i wolałbym nie używać XML).

Czy istnieje sposób serializacji obiektów do łańcuchów JSON UTF-8 (zamiast \uXXXX)?

Author: Boris, 2013-08-20

12 answers

Użyj przełącznika ensure_ascii=False na json.dumps(), a następnie ręcznie Zakoduj wartość do 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())
"ברי צקלה"

Jeśli zapisujesz do pliku, po prostu użyj json.dump() i pozostaw go obiektowi file do zakodowania:

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

Caveats for Python 2

W Pythonie 2 należy wziąć pod uwagę jeszcze kilka zastrzeżeń. Jeśli zapisujesz to do pliku, możesz użyć io.open() zamiast open() do tworzenia obiektu file, który koduje wartości Unicode podczas pisania, użyj zamiast tego json.dump() aby zapisać do tego pliku:

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

Zwróć uwagę, że w module json {27]} występuje błąd , w którym znacznik ensure_ascii=False może wytworzyć mieszankę obiektów unicode i str. Obejście problemu dla Pythona 2 to:

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

W Pythonie 2, Gdy używasz łańcuchów bajtów (type str), zakodowanych w UTF-8, upewnij się, że ustawisz również słowo kluczowe encoding:

>>> 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']
ברי צקלה
 772
Author: Martijn Pieters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-08 09:01:38

Aby zapisać do pliku

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)

To print to stdout

import json
print(json.dumps({"message":"xin chào việt nam"}, ensure_ascii=False))
 86
Author: Trần Quang Hiệp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-30 23:28:48

Aktualizacja: to zła odpowiedź, ale nadal warto zrozumieć, dlaczego jest zła. Zobacz komentarze.

A może unicode-escape?

>>> d = {1: "ברי צקלה", 2: u"ברי צקלה"}
>>> json_str = json.dumps(d).decode('unicode-escape').encode('utf8')
>>> print json_str
{"1": "ברי צקלה", "2": "ברי צקלה"}
 28
Author: monitorius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-13 09:18:56

Obejście Pythona 2 Petersa nie powiodło się w przypadku edge:

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)
Rozbijał się o ...decode ('utf8') część linii 3. Naprawiłem problem, upraszczając program, unikając tego kroku, a także specjalnej obudowy ascii:
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"}
 26
Author: Jonathan Ray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-08 10:28:25

Od wersji Python 3.7 następujący kod działa poprawnie:

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

Wyjście:

{"symbol": "ƒ"}
 10
Author: Nik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-20 13:56:37

Poniżej znajduje się moje zrozumienie var czytając odpowiedź powyżej i 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'
"""
 7
Author: Cheney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-09 07:06:06

Oto moje rozwiązanie przy użyciu 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)

Gdzie SYSTEM_ENCODING jest ustawiony na:

locale.setlocale(locale.LC_ALL, '')
SYSTEM_ENCODING = locale.getlocale()[1]
 5
Author: Neit Sabes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-26 09:56:06

Użyj kodeków, jeśli to możliwe,

with codecs.open('file_path', 'a+', 'utf-8') as fp:
    fp.write(json.dumps(res, ensure_ascii=False))
 4
Author: Yulin GUO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 06:58:31

Dzięki za oryginalną odpowiedź tutaj. Z python 3 następujący wiersz kodu:

print(json.dumps(result_dict,ensure_ascii=False))
Było ok. Zastanów się nad tym, aby nie pisać zbyt dużo tekstu w kodzie, jeśli nie jest to konieczne.

To może być wystarczająco dobre dla konsoli Pythona. Jednak, aby zaspokoić serwer może być konieczne ustawienie locale jak wyjaśniono tutaj (jeśli jest na apache2) http://blog.dscpl.com.au/2014/09/setting-lang-and-lcall-when-using.html

W zasadzie zainstaluj he_IL czy cokolwiek ustawienia językowe w ubuntu sprawdź, czy nie jest zainstalowany

locale -a 

Zainstaluj go tam, gdzie XX jest twoim językiem

sudo apt-get install language-pack-XX

Na przykład:

sudo apt-get install language-pack-he
Zapraszamy do zapoznania się z naszą ofertą]}
export LANG='he_IL.UTF-8'
export LC_ALL='he_IL.UTF-8'

Niż mam nadzieję, że nie dostaniesz błędów Pythona z apache jak:

Print (js) UnicodeEncodeError: kodek 'ascii' nie może kodować znaków w pozycji 41-45: ordinal not in range(128)

Również w apache spróbuj ustawić utf jako domyślne kodowanie jak wyjaśniono tutaj:
Jak zmienić domyślne kodowanie na UTF-8 dla Apache?

Zrób to wcześnie, ponieważ błędy apache mogą być bolesne do debugowania i możesz błędnie pomyśleć, że to z Pythona, co prawdopodobnie nie jest w tej sytuacji

 2
Author: sivi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-25 09:13:12

Jeśli wczytywasz tekst JSON z pliku i zawartości pliku. Więc to zadziała.

Załóżmy Plik jak: arabic.json

{ 
"key1" : "لمستخدمين",
"key2" : "إضافة مستخدم"
}

Pobierz arabską zawartość z arabskiego.plik json

with open(arabic.json, encoding='utf-8') as f:
   # deserialises it
   json_data = json.load(f)
   f.close()


# json formatted string
json_data2 = json.dumps(json_data, ensure_ascii = False)

Aby użyć danych JSON w szablonie Django wykonaj poniższe kroki:

# If have to get the JSON index in Django Template file, then simply decode the encoded string.

json.JSONDecoder().decode(json_data2)
Zrobione! Teraz możemy uzyskać wyniki jako indeks JSON z arabską wartością.
 2
Author: Chandan Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-26 09:49:26

Użyj Unicode-escape, aby rozwiązać problem

>>>import json
>>>json_string = json.dumps("ברי צקלה")
>>>json_string.encode('ascii').decode('unicode-escape')
'"ברי צקלה"'

Wyjaśnij

>>>s = '漢  χαν  хан'
>>>print('unicode: ' + s.encode('unicode-escape').decode('utf-8'))
unicode: \u6f22  \u03c7\u03b1\u03bd  \u0445\u0430\u043d

>>>u = s.encode('unicode-escape').decode('utf-8')
>>>print('original: ' + u.encode("utf-8").decode('unicode-escape'))
original: 漢  χαν  хан

Oryginalny zasób: https://blog.csdn.net/chuatony/article/details/72628868

 0
Author: ChrisXiao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-23 09:58:43

Używanie ensure_ascii = False w json.dumps jest właściwym kierunkiem rozwiązania tego problemu, jak wskazał Martijn. Jednak może to spowodować wyjątek:

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

Potrzebne są dodatkowe ustawienia w site.py lub sitecustomize.py aby ustawić swój sys.getdefaultencoding () poprawne. site.py jest pod lib / python2. 7 / i sitecustomize.py jest pod lib / python2.7 / site-packages.

Jeśli chcesz użyć site.py, pod def setencoding (): Zmień pierwsze if 0: Na if 1: tak aby python używał Twojego lokalizacja systemu operacyjnego.

Jeśli wolisz używać sitecustomize.py, który może nie istnieć, jeśli go nie stworzyłeś. po prostu te linie:

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

Następnie możesz wykonać niektóre chińskie wyjście json w formacie utf-8, takie jak:

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

Otrzymasz kodowany łańcuch utf-8, zamiast \ u \ u000f \ u000f \ u000f \ u000f \ u000f.

Aby zweryfikować domyślne kodowanie:

print sys.getdefaultencoding()

Powinieneś uzyskać "utf-8" lub "UTF-8", aby zweryfikować swoje site.py lub sitecustomize.py ustawienia.

Uwaga tego nie mogłeś zrobić.setdefaultencoding ("utf-8") w interaktywnej konsoli Pythona.

 -3
Author: Ryan X,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-05 02:25:35