json.dumps에서 utf-8 텍스트를 \ u 이스케이프 시퀀스가 ​​아닌 UTF8로 저장


474

샘플 코드 :

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

문제 : 사람이 읽을 수 없습니다. 내 (스마트) 사용자는 JSON 덤프로 텍스트 파일을 확인하거나 편집하려고합니다 (XML을 사용하지 않겠습니다).

객체 대신 UTF-8 JSON 문자열로 객체를 직렬화하는 방법이 \uXXXX있습니까?


9
+ for ברי צקלה :)))
rubmz

답변:


641

ensure_ascii=False스위치를 사용하여 json.dumps()값을 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())
"ברי צקלה"

파일에 쓰고 있다면 json.dump()인코딩하고 파일 객체에 그대로 두십시오.

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

파이썬 2에 대한 경고

파이썬 2의 경우 고려해야 할 몇 가지주의 사항이 있습니다. 이것을 파일에 쓰는 경우 io.open()대신 open()유니 코드 값을 인코딩하는 파일 객체를 생성하는 대신 대신 사용할 수 있습니다 json.dump().

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

있음을 유의 수행 버그 json모듈ensure_ascii=False 플래그가 생산할 수있는 혼합unicodestr객체. Python 2의 해결 방법은 다음과 같습니다.

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

Python 2에서는 strUTF-8로 인코딩 된 바이트 문자열 (type )을 사용할 때 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']
ברי צקלה

72

파일에 쓰려면

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)

표준 출력으로 인쇄하려면

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

1
구문 오류 : 5 행의 json-utf8.py 파일에있는 비 ASCII 문자 '\ xc3'이지만 선언 된 인코딩이 없습니다. 자세한 내용은 python.org/dev/peps/pep-0263 을 참조하십시오
Alex

감사합니다! 나는 그것이 그렇게 단순하다는 것을 몰랐다. json으로 변환하는 데이터가 신뢰할 수없는 사용자 입력 인 경우에만주의해야합니다.
Karim Sonbol

@Alex 당신은 그 문제를 피하는 방법을 알아 냈습니까?
가브리엘 페어

@Gabriel 솔직히 기억이 나지 않습니다. 발췌 문장을 제쳐두는 것이 그렇게 중요하지 않았습니다. (
Alex

codecs도서관을 이용해서 만 일했습니다 . 감사!
igorkf

29

업데이트 : 이것은 잘못된 대답이지만 왜 그것이 잘못되었는지 이해하는 것이 여전히 유용합니다. 의견을 참조하십시오.

어때요 unicode-escape?

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

9
unicode-escape필요하지 않습니다 : json.dumps(d, ensure_ascii=False).encode('utf8')대신 사용할 수 있습니다 . 그리고 json 이 모든 경우 에 파이썬의 코덱 과 정확히 동일한 규칙을 사용한다고 보장하지는 않습니다. 즉, 일부 경우에 결과가 같거나 같지 않을 수 있습니다. downvote는 불필요하고 잘못된 변환을위한 것입니다. 관련이 없음 : utf8 로케일 또는 envvar가 여기에서 utf8을 지정하는 경우에만 작동합니다 (대신 유니 코드 인쇄). unicode-escapeprint json_strPYTHONIOENCODING
jfs

3
또 다른 문제 : 문자열 값의 큰 따옴표는 이스케이프를 잃어 버리므로 JSON 출력이 손상 됩니다.
Martijn Pieters

Python3의 오류 : AttributeError : 'str'객체에 'decode'속성이 없습니다.
Gank

1
유니 코드 이스케이프가 잘 작동합니다! 이 답변을 올바른 것으로 받아 들일 것입니다.
노동자

@jfs 아니요, json.dumps(d, ensure_ascii=False).encode('utf8')적어도 작동하지 않습니다. 나는군요 UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position ...-error합니다. 그러나 unicode-escape변형이 잘 작동합니다.
turingtest

24

Peters의 python 2 해결 방법은 간결한 경우에 실패합니다.

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)

3 행의 .decode ( 'utf8') 부분에서 충돌이 발생했습니다. 나는 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"}

2
'가장자리 사례'는 단순히 내 테스트에서 멍청한 테스트되지 않은 오류였습니다. 당신의 unicode(data)접근 방식은 더 나은 옵션이 아닌 예외 처리를 사용합니다. 점을 유의 encoding='utf8'키워드 인수는 출력과는 아무 상관이없는 json.dumps()생산을; 함수가받는 str입력 을 디코딩하는 데 사용됩니다 .
Martijn Pieters

2
@MartijnPieters : 또는 더 단순 : 리턴 (아스키 전용) str 또는 유니 코드 객체 open('filename', 'wb').write(json.dumps(d, ensure_ascii=False).encode('utf8'))여부에 관계없이 작동합니다 dumps.
jfs

@JFSebastian : 암묵적으로 먼저 str.encode('utf8') 디코딩 하기 때문에 맞습니다 . 그러나 객체 unicode(data)가 주어지면 그렇게 str합니다. :-) Using io.open()는 BOM을 작성하는 코덱을 사용하는 것을 포함하여 더 많은 옵션을 제공하며 JSON 데이터를 다른 것으로 따르고 있습니다.
Martijn Pieters

@MartijnPieters : .encode('utf8')기반 변형은 Python 2와 3 (동일한 코드)에서 작동합니다. unicodePython 3 에는 없습니다 . 관련 이 없음 : json 파일은 BOM을 사용하지 않아야합니다 (확인 json 구문 분석기는 BOM을 무시할 수 있지만 오류 3983 참조 ).
jfs

추가 하여 문제 encoding='utf8'json.dumps해결합니다. 추신 : 나는 키릴 텍스트를 가지고 있습니다
Max L

8

Python 3.7부터 다음 코드는 정상적으로 작동합니다.

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

산출:

{"symbol": "ƒ"}

2
파이썬 3.6에서도 (확인되었습니다).
Berry Tsakala

7

다음은 위의 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'
"""

5

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)

여기서 SYSTEM_ENCODING은 다음으로 설정됩니다.

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

4

가능하면 코덱을 사용하십시오.

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

1

원래 답변을 보내 주셔서 감사합니다. 와 파이썬 3 다음 코드 줄 :

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

괜찮 았어 필수가 아닌 경우 코드에 너무 많은 텍스트를 쓰지 마십시오.

이것은 파이썬 콘솔에 충분할 것입니다. 그러나 서버를 만족시키기 위해 여기에 설명 된대로 (아파치 2에있는 경우) 로케일을 설정해야 할 수도 있습니다. http://blog.dscpl.com.au/2014/09/setting-lang-and-lcall-when-using .html

기본적으로 우분투에 he_IL 또는 다른 언어 로케일을 설치하십시오.

locale -a 

XX가 귀하의 언어 인 곳에 설치하십시오

sudo apt-get install language-pack-XX

예를 들면 다음과 같습니다.

sudo apt-get install language-pack-he

/ etc / apache2 / envvrs에 다음 텍스트를 추가하십시오

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

아파치에서 파이썬 오류가 발생하지 않기를 바랍니다.

print (js) UnicodeEncodeError : 'ascii'코덱이 41-45 위치의 문자를 인코딩 할 수 없습니다 : 서 수가 범위 내에 있지 않습니다 (128)

또한 아파치에서 여기에 설명 된 것처럼 utf를 기본 인코딩으로 만드십시오.
기본 인코딩을 Apache의 UTF-8로 변경하는 방법은 무엇입니까?

아파치 오류는 디버깅하기가 어려울 수 있기 때문에 일찍 수행하고 실수로 파이썬에서 발생한 것으로 생각할 수 있습니다.


1

파일 및 파일 내용 아랍어 텍스트에서 JSON 문자열을로드하는 경우 그런 다음 작동합니다.

파일을 다음과 같이 가정하십시오 : arabic.json

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

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

장고 템플릿에서 JSON 데이터를 사용하려면 다음 단계를 따르십시오.

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

json.JSONDecoder().decode(json_data2)

끝난! 이제 아랍어 값으로 JSON 인덱스로 결과를 얻을 수 있습니다.


fh.close() fh정의되지 않았습니다.
AMC

이제 수정되었습니다. 그것은 것f.close()
이것을 Chandan 샤르마

0

유니 코드 이스케이프를 사용하여 문제 해결

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

설명

>>>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:   χαν  хан

원본 자료 :https://blog.csdn.net/chuatony/article/details/72628868


-3

Martijn이 지적한 것처럼 json.dumps에서 ensure_ascii = False를 사용하는 것이이 문제를 해결하는 올바른 방향입니다. 그러나 이로 인해 예외가 발생할 수 있습니다.

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

sys.getdefaultencoding ()을 올바르게 설정하려면 site.py 또는 sitecustomize.py에 추가 설정이 필요합니다. site.py는 lib / python2.7 /에 있고 sitecustomize.py는 lib / python2.7 / site-packages에 있습니다.

def setencoding ()에서 site.py를 사용하려면 python이 운영 체제의 로케일을 사용하도록 0을 if :로 변경하십시오.

sitecustomize.py를 사용하려는 경우이를 작성하지 않은 경우 존재하지 않을 수 있습니다. 간단히 다음 줄을 넣으십시오.

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

그런 다음 utf-8 형식으로 중국어 json 출력을 수행 할 수 있습니다.

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

\ u 이스케이프 된 json 문자열 대신 utf-8로 인코딩 된 문자열을 얻습니다.

기본 인코딩을 확인하려면

print sys.getdefaultencoding()

site.py 또는 sitecustomize.py 설정을 확인하려면 "utf-8"또는 "UTF-8"이 표시되어야합니다.

대화식 파이썬 콘솔에서는 sys.setdefaultencoding ( "utf-8")을 수행 할 수 없습니다.


2
아니. 하지마 기본 문자 인코딩 수정과는 아무 상관이 없습니다 json들 ' ensure_ascii=False. 다르게 생각한다면 최소한의 완전한 코드 예제를 제공하십시오.
jfs

비 ASCII 바이트 문자열 (예 : 유니 코드 값이 아님)을 피드 하거나 결과 JSON 값 (유니 코드 문자열)을 비 ASCII 바이트 문자열과 결합하려는 경우에만이 예외 가 발생합니다. 기본 인코딩을 UTF-8로 설정하면 문자열 데이터를 제대로 관리하지 않았을 때 근본적인 문제를 숨길 수 있습니다.
Martijn Pieters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.