JSON에서 유니코드 대신 문자열 객체를 가져오는 방법
Python 2를 사용하여 ASCII로 인코딩된 텍스트 파일에서 JSON을 구문 분석할 겁니다.
이러한 파일을 로딩할 때 또는 로 모든 문자열 값이 문자열 개체 대신 유니코드 개체로 캐스트된다.문제는 문자열 개체만 허용하는 일부 라이브러리와 함께 데이터를 사용해야 한다는 겁니다.나는 도서관을 바꿀 수도 없고 갱신할 수도 없다.
유니코드 대신 문자열 오브젝트를 얻는 것이 가능한가?
예
>>> import json
>>> original_list = ['a', 'b']
>>> json_list = json.dumps(original_list)
>>> json_list
'["a", "b"]'
>>> new_list = json.loads(json_list)
>>> new_list
[u'a', u'b'] # I want these to be of type `str`, not `unicode`
갱신하다
이 질문은 내가 파이톤 2에 갇혀 있을 때, 오래 전에 물어본 것이다.오늘날의 쉽고 깨끗한 해결책은 파이썬의 최신 버전, 즉 파이썬을 사용하는 것이다.파이톤 3번, 앞으로.
여기에 좋은 답이 몇 개 있지만, 나는 결국 PyYAML을 사용하여 JSON 파일을 구문 분석하게 되었는데, 그것은 키와 값을 다음과 같이 제공하기 때문이다.str
대신 문자열을 입력하다unicode
JSON은 YAML의 서브셋이기 때문에 잘 작동한다.
>>> import json
>>> import yaml
>>> list_org = ['a', 'b']
>>> list_dump = json.dumps(list_org)
>>> list_dump
'["a", "b"]'
>>> json.loads(list_dump)
[u'a', u'b']
>>> yaml.safe_load(list_dump)
['a', 'b']
메모들
다음 사항에 유의하십시오.
모든 항목이 ASCII 인코딩되었기 때문에 문자열 개체를 얻는다.유니코드 인코딩된 항목을 사용할 경우 유니코드 개체로 다시 가져올 수 있지만 변환할 수 없음!
Py를 사용해야 한다(아마도 항상).YAML의
safe_load
기능; JSON 파일을 로드하는 데 사용할 경우, 의 "추가 전원"이 필요하지 않음load
어쨌든 기능을 발휘하다1.2 버전의 사양에 대한 지원을 더 많이 제공하는 YAML 파서를 원하는 경우(그리고 매우 낮은 숫자를 올바르게 구문) Ruamel YAML을 사용해 보십시오.
pip install ruamel.yaml
그리고import ruamel.yaml as yaml
내 시험에서 필요한 건 그게 다였어
전환
말했듯이, 변환은 없어!ASCII 값만 처리할 수 없고 대부분의 경우 확신할 수 없는 경우 변환 함수를 사용하는 것이 좋다.
나는 마크 아메리의 것을 지금 몇 번 사용했는데, 그것은 잘 작동하고 사용하기 매우 쉽다.또한 유사한 기능을 사용할 수 있다.object_hook
대신 대용량 파일의 성능을 향상시킬 수 있기 때문에그것에 대한 미레크 미스쿠프로부터 조금 더 관련 있는 대답을 보라.
유니코드 문자열 대신 json 모듈 기능이 바이트 문자열을 반환하도록 하는 내장 옵션이 없다.그러나 이 짧고 단순한 재귀 함수는 디코딩된 JSON 개체를 유니코드 문자열을 사용하는 것에서 UTF-8 인코딩된 바이트 문자열로 변환한다.
def byteify(input):
if isinstance(input, dict):
return {byteify(key): byteify(value)
for key, value in input.iteritems()}
elif isinstance(input, list):
return [byteify(element) for element in input]
elif isinstance(input, unicode):
return input.encode('utf-8')
else:
return input
이 호출은 다음에서 얻은 출력하십시오.json.load
또는json.loads
전화를 걸다
몇 가지 참고 사항:
- Python 2.6 이전 버전을 지원하려면 교체하십시오.
return {byteify(key): byteify(value) for key, value in input.iteritems()}
와 함께return dict([(byteify(key), byteify(value)) for key, value in input.iteritems()])
Python 2.7까지는 사전 포괄이 지원되지 않았기 때문에. - 이 해답은 디코딩된 물체 전체를 통해 반복되기 때문에 매우 세심한 사용으로 피할 수 있는 몇 가지 바람직하지 않은 성능 특성을 가지고 있다.
object_hook
또는object_pairs_hook
매개변수.미레크 미스코프의 대답은 지금까지 이 일을 제대로 해낸 유일한 것이지만, 그 결과 내 접근법보다 훨씬 더 복잡하다.
와의 해결책.object_hook
[edit]: Python 2.7 및 3.x 호환성에 대해 업데이트됨.
import json
def json_load_byteified(file_handle):
return _byteify(
json.load(file_handle, object_hook=_byteify),
ignore_dicts=True
)
def json_loads_byteified(json_text):
return _byteify(
json.loads(json_text, object_hook=_byteify),
ignore_dicts=True
)
def _byteify(data, ignore_dicts = False):
if isinstance(data, str):
return data
# if this is a list of values, return list of byteified values
if isinstance(data, list):
return [ _byteify(item, ignore_dicts=True) for item in data ]
# if this is a dictionary, return dictionary of byteified keys and values
# but only if we haven't already byteified it
if isinstance(data, dict) and not ignore_dicts:
return {
_byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True)
for key, value in data.items() # changed to .items() for python 2.7/3
}
# python 3 compatible duck-typing
# if this is a unicode string, return its string representation
if str(type(data)) == "<type 'unicode'>":
return data.encode('utf-8')
# if it's anything else, return it in its original form
return data
사용 예:
>>> json_loads_byteified('{"Hello": "World"}')
{'Hello': 'World'}
>>> json_loads_byteified('"I am a top-level string"')
'I am a top-level string'
>>> json_loads_byteified('7')
7
>>> json_loads_byteified('["I am inside a list"]')
['I am inside a list']
>>> json_loads_byteified('[[[[[[[["I am inside a big nest of lists"]]]]]]]]')
[[[[[[[['I am inside a big nest of lists']]]]]]]]
>>> json_loads_byteified('{"foo": "bar", "things": [7, {"qux": "baz", "moo": {"cow": ["milk"]}}]}')
{'things': [7, {'qux': 'baz', 'moo': {'cow': ['milk']}}], 'foo': 'bar'}
>>> json_load_byteified(open('somefile.json'))
{'more json': 'from a file'}
이것은 어떻게 작동하며 내가 왜 그것을 사용하겠는가?
마크 아메리의 기능은 이들보다 짧고 또렷한데, 도대체 무슨 의미가 있는 것일까?왜 그것들을 사용하려고 하십니까?
순수하게 퍼포먼스를 위해서.마크의 대답은 유니코드 문자열로 먼저 JSON 텍스트를 완전히 해독한 다음, 디코딩된 전체 값을 통해 반복하여 모든 문자열을 바이트 문자열로 변환한다.이는 몇 가지 바람직하지 않은 효과를 가진다.
- 디코딩된 전체 구조의 복사본이 메모리에 생성됨
- JSON 객체가 정말로 내포된 경우(500레벨 이상) 파이썬의 최대 재귀 깊이에 도달하게 된다.
이 답변은 다음을 사용하여 두 가지 성능 문제를 완화한다.object_hook
의 매개 변수.json.load
그리고json.loads
. 문서에서:
object_hook
그대로 )dict
object_hook의 을 object_hook의 은은은 대신 한다.dict
이 기능은 사용자 정의 디코더를 구현하는 데 사용할 수 있다.
사전이 다른 사전의 깊은 곳에 많은 레벨이 중첩되어 있기 때문에object_hook
해독될 때, 우리는 어떤 문자열이나 목록도 바이트로 만들 수 있고 나중에 깊은 재귀가 필요하지 않게 할 수 있다.
마크의 대답은 어원으로 쓰기에 적합하지 않다.object_hook
현재 상태로는 중첩된 사전으로 재귀가 되기 때문이다.우리는 이 대답에서 그 재귀들을 예방한다.ignore_dicts
에 대한 매개 변수._byteify
, 그리고 그것은 언제가 아닌 항상 그것에 전달된다.object_hook
그것을 새로운 것으로 바꾸다.dict
바이트 단위로 표시하다그ignore_dicts
국기가 전하다._byteify
무시하다dict
s 이미 바이트로 지정되었기 때문에.
마지막으로, 우리의 구현은json_load_byteified
그리고json_loads_byteified
전화를 걸다_byteify
(와 함께)ignore_dicts=True
에서 반환된 결과에 대해json.load
또는json.loads
를 다루자면 JSON 텍스트에 JSON이 없는 경우 입니다.dict
최상급의
당신은 그것을 사용할 수 있다.object_hook
변환기에서 전달하기 위한 매개 변수.사실 이후에 변환을 할 필요는 없다.모듈은 항상 다음을 통과한다.object_hook
받아쓰기만 하고, 다시 내포된 받아쓰기를 반복적으로 통과하게 되므로 내포된 받아쓰기를 반복할 필요가 없다.나는 유니코드 문자열을 웰스 쇼처럼 숫자로 변환하지 않을 것 같아.유니코드 문자열이라면 JSON 파일에서 문자열로 인용되었으므로 문자열(또는 파일이 불량)으로 되어 있다.
또한, 나는 이런 일을 피하려고 노력한다.str(val)
에서unicode
이의를 제기하다당신은 사용해야만 한다.value.encode(encoding)
외부 lib가 기대하는 바에 따라 유효한 인코딩을 사용하여.
예를 들어,
def _decode_list(data):
rv = []
for item in data:
if isinstance(item, unicode):
item = item.encode('utf-8')
elif isinstance(item, list):
item = _decode_list(item)
elif isinstance(item, dict):
item = _decode_dict(item)
rv.append(item)
return rv
def _decode_dict(data):
rv = {}
for key, value in data.iteritems():
if isinstance(key, unicode):
key = key.encode('utf-8')
if isinstance(value, unicode):
value = value.encode('utf-8')
elif isinstance(value, list):
value = _decode_list(value)
elif isinstance(value, dict):
value = _decode_dict(value)
rv[key] = value
return rv
obj = json.loads(s, object_hook=_decode_dict)
json은 문자열 개체와 유니코드 개체 사이에 차이가 없기 때문이다.모두 자바스크립트의 현이다.
유니코드 객체를 반환하는 것은 JSON이 옳다고 생각한다.사실, 나는 Javascript 문자열이 사실 객체(즉, JSON (Javascript) 문자열은 어떤 종류의 유니코드 문자도 저장할 수 있기 때문에 그것을 만드는 것이 이치에 맞기 때문에 그 어떤 것도 받아들이지 않을 것이다.unicode
JSON에서 문자열을 변환할 때 객체.일반 문자열은 라이브러리가 원하는 인코딩을 맞춰야 하기 때문에 맞지 않을 것이다.
사용하는 것이 좋다.unicode
할 수 도서관을 따라서 가장 좋은 옵션은 유니코드 개체를 처리할 수 있도록 라이브러리를 업데이트하는 것이다.
하지만 정말로 바이테스트링을 원한다면 원하는 인코딩에 결과를 인코딩하십시오.
>>> nl = json.loads(js)
>>> nl
[u'a', u'b']
>>> nl = [s.encode('utf-8') for s in nl]
>>> nl
['a', 'b']
손쉬운 해결책이 존재한다.
- TL;DR - 사ast.literal_eval()
대신에json.loads()
. 둘 다ast
그리고json
표준 도서관에 있다.
'완벽한' 대답은 아니지만, 유니코드를 완전히 무시하려는 계획이라면 꽤 먼 답을 얻을 수 있다.Python 2.7에서
import json, ast
d = { 'field' : 'value' }
print "JSON Fail: ", json.loads(json.dumps(d))
print "AST Win:", ast.literal_eval(json.dumps(d))
다음을 제공한다.
JSON Fail: {u'field': u'value'}
AST Win: {'field': 'value'}
이것은 어떤 물체들이 정말로 유니코드 문자열일 때 더 털이 많아진다.풀 해답은 금방 털털해진다.
마이크 브레넌의 대답은 가깝지만, 구조 전체를 재횡단할 이유는 없다.(Python 2.7+) 파라미터를 사용하는 경우:
object_pairs_hook
순서가 지정된 쌍 목록으로 디코딩된 개체 리터럴의 결과와 함께 호출되는 선택적 함수다.반환 값은 다음 값 대신dict
. 이 기능은 키와 값 쌍이 디코딩되는 순서에 의존하는 사용자 정의 디코더를 구현하는 데 사용할 수 있다(예:collections.OrderedDict
삽입 순서를 기억할 것이다.만약 또한 정의된다면, 는 우선권을 갖는다.
이를 통해 각 JSON 개체를 전달받으므로 반복할 필요 없이 디코딩을 수행할 수 있다.
def deunicodify_hook(pairs):
new_pairs = []
for key, value in pairs:
if isinstance(value, unicode):
value = value.encode('utf-8')
if isinstance(key, unicode):
key = key.encode('utf-8')
new_pairs.append((key, value))
return dict(new_pairs)
In [52]: open('test.json').read()
Out[52]: '{"1": "hello", "abc": [1, 2, 3], "def": {"hi": "mom"}, "boo": [1, "hi", "moo", {"5": "some"}]}'
In [53]: json.load(open('test.json'))
Out[53]:
{u'1': u'hello',
u'abc': [1, 2, 3],
u'boo': [1, u'hi', u'moo', {u'5': u'some'}],
u'def': {u'hi': u'mom'}}
In [54]: json.load(open('test.json'), object_pairs_hook=deunicodify_hook)
Out[54]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
당신이 고리를 사용할 때 모든 물체가 고리에 전달되기 때문에 나는 고리를 재귀적으로 부를 필요가 없다는 것을 알아두시오.object_pairs_hook
리스트에 신경을 써야 하지만, 보다시피 리스트 안에 있는 물체는 적절하게 변환될 것이고, 그것을 실현하기 위해 반복할 필요는 없다.
한 동료가 6에 집 동봉가 Python2가 했다.6에 파이톤2.6이 없다고 지적했다.object_hook_pairs
당신은 여전히 이것을 아주 작은 변화로 Python2.6을 사용할 수 있다.위의 후크에서 다음을 변경하십시오.
for key, value in pairs:
로
for key, value in pairs.iteritems():
그 다음 사용object_hook
대신에object_pairs_hook
:
In [66]: json.load(open('test.json'), object_hook=deunicodify_hook)
Out[66]:
{'1': 'hello',
'abc': [1, 2, 3],
'boo': [1, 'hi', 'moo', {'5': 'some'}],
'def': {'hi': 'mom'}}
사용.object_pairs_hook
JSON 오브젝트의 각 오브젝트에 대해 하나의 사전이 덜 인스턴스화됨으로써, 만약 당신이 거대한 문서를 구문 분석한다면, 그것은 가치가 있을 것이다.
나는 이 간단한 도서관 안에서 이것을 자동으로 이룰 방법이 없을까 봐 걱정이다.
심플json의 스캐너와 디코더는 유니코드 텍스트를 만들도록 설계되었다.이를 위해 도서관은 '이름'이라는 함수를 사용한다.c_scanstring
(속도를 위해 사용 가능한 경우) 또는py_scanstring
C 버전을 사용할 수 없는 경우.그scanstring
함수는 simplejson이 텍스트를 포함할 수 있는 구조를 해독하기 위해 가지고 있는 거의 모든 루틴에 의해 여러 번 불린다.넌 그 일을 망쳐버려야 할거야scanstring
simplejson.decoder의 은 haughdo의 스이다.JSONDecoder
텍스트가 포함될 수 있는 모든 구현을 직접 제공하십시오.
그러나 단순 json이 유니코드를 출력하는 이유는 json 스펙에서 " 문자열은 0개 이상의 유니코드 문자의 집합"이라고 구체적으로 언급하기 때문이다... 유니코드에 대한 지원은 형식 자체의 일부로 상정된다.심플지슨스scanstring
구현은 유니코드 이스케이프(잘못된 형식의 멀티바이트 문자 집합 표현에 대한 오류 발생까지)를 스캔하고 해석하기 때문에, 유니코드로서 그 값을 신뢰성 있게 반환할 수 있는 유일한 방법은 유니코드로서이다.
만약 당신이 오래된 도서관을 가지고 있다면, 그 도서관이 필요한 것은str
, 구문 분석 후 내포된 데이터 구조를 힘들게 검색하거나 둘 중 하나를 추천한다. (이것은 분명히 피하고 싶다고 말한 것을 인정한다...죄송합니다), 또는 입력 매개 변수를 보다 세부적인 수준에서 마사지할 수 있는 일종의 측면으로 라이브러리를 감싸십시오.두 번째 접근방식은 데이터 구조가 실제로 내포되어 있는 경우 첫 번째 접근방식보다 더 관리가 용이할 수 있다.
표시(아메리)가 올바르게 기록한 대로:json 덤프에서 PyYaml의 탈세리알라이저를 사용하는 것은 ASCII만 있는 경우에만 작동한다.적어도 박스 밖으로.
PyYaml 접근법에 대한 두 가지 빠른 의견:
현장에서 가져온 데이터에 yaml.load를 사용하지 마십시오.구조 내에 숨겨진 임의 코드를 실행하는 yaml의 기능(!)이다.
다음을 통해 비 ASCII에서도 작동하도록 할 수 있다.
def to_utf8(loader, node): return loader.construct_scalar(node).encode('utf-8') yaml.add_constructor(u'tag:yaml.org,2002:str', to_utf8)
그러나 성능은 마크 아메리의 대답과는 비교가 되지 않는다.
깊이 중첩된 샘플 몇 개를 두 가지 방법으로 던지면, 나는 다음과 같은 것을 얻는다(dt[j] = json.loads(json.dumps(m)의 시간 델타:
dt[yaml.safe_load(json.dumps(m))] =~ 100 * dt[j]
dt[byteify recursion(Mark Amery)] =~ 5 * dt[j]
따라서 나무를 완전히 걷고 인코딩하는 등 탈직렬화(deserialization)는 json의 C 기반 구현의 정도 범위 내에서 이루어진다.나는 이것이 매우 빠르고 또한 깊은 내포 구조에서 yaml 부하보다 더 강력하다는 것을 알았다.그리고 보안 오류 발생률이 낮아지고 yaml.load를 볼 수 있음.
=> C 기반 변환기에 대한 포인터는 고맙지만 바이트 표시 함수는 기본 답이 되어야 한다.
이는 특히 json 구조가 사용자 입력을 포함하는 필드에서 가져온 경우 더욱 유효하다.그렇다면 원하는 내부 데이터 구조('유니코드 샌드위치' 또는 바이트 문자열에만 해당)를 독립적으로 사용하는 구조 위를 걸어가야 할 수 있기 때문이다.
왜?
유니코드 정규화.알지 못하는 경우:진통제를 먹고 이것을 읽어라.
그래서 바이트 단위 재귀로 일석이조의 새를 죽는다.
- 중첩된 json 덤프에서 당신의 bytesting을 가져오다.
- 사용자 입력 값을 정규화하여 스토리지에서 원하는 항목을 찾으십시오.
내 테스트에서 input.encode('utf-8')를 유니코다타.normalize('NFC', input.encode('utf-8')로 대체하는 것이 근거리 무선 통신보다 훨씬 빠르지만, 이는 표본 데이터에 크게 의존하는 것으로 나타났다.
요점은 이다.simplejson
그리고json
적어도 유니코드를 다루는 방식에서는 두 개의 다른 모듈이다.당신은 가지고 있다json
fy 2.6+에서 유니코드 값을 제공하는 반면simplejson
문자열 개체를 반환하십시오.사용자 환경에서 간편 설치 Simplejson을 사용해 보십시오.나한텐 그랬어.
json 대신 피클을 사용해서 덤프나 짐을 부려라.
import json
import pickle
d = { 'field1': 'value1', 'field2': 2, }
json.dump(d,open("testjson.txt","w"))
print json.load(open("testjson.txt","r"))
pickle.dump(d,open("testpickle.txt","w"))
print pickle.load(open("testpickle.txt","r"))
생산되는 출력은 다음과 같다(스트링과 정수가 올바르게 처리됨):
{u'field2': 2, u'field1': u'value1'}
{'field2': 2, 'field1': 'value1'}
그래서 나도 같은 문제에 부딪혔다.구글의 첫 번째 결과가 무엇이었는지 추측해보라.
모든 데이터를 PyGTK에 전달해야 하기 때문에 유니코드 문자열도 내게는 그다지 유용하지 않다.그래서 나는 또 다른 재귀적 변환 방법을 가지고 있다.그것은 실제로 JSON 타입 변환에도 필요하다 - json.dump()는 Python 물체와 같은 비문학자에게도 보석금을 지불할 것이다.하지만 받아쓰기 인덱스는 변환하지 않는다.
# removes any objects, turns unicode back into str
def filter_data(obj):
if type(obj) in (int, float, str, bool):
return obj
elif type(obj) == unicode:
return str(obj)
elif type(obj) in (list, tuple, set):
obj = list(obj)
for i,v in enumerate(obj):
obj[i] = filter_data(v)
elif type(obj) == dict:
for i,v in obj.iteritems():
obj[i] = filter_data(v)
else:
print "invalid object in data, converting to string"
obj = str(obj)
return obj
나는 JSON을 끈으로 받아쓰게 했다.키와 값은 다음과 같은 유니코드 객체였다.
myStringDict = "{u'key':u'value'}"
나는 그것을 사용할 수 있다.byteify
문자열을 a로 변환하여 위에 제안된 함수dict
을 반대하다.ast.literal_eval(myStringDict)
.
후크를 사용하여 Python2&3 지원(https://stackoverflow.com/a/33571117/558397)
import requests
import six
from six import iteritems
requests.packages.urllib3.disable_warnings() # @UndefinedVariable
r = requests.get("http://echo.jsontest.com/key/value/one/two/three", verify=False)
def _byteify(data):
# if this is a unicode string, return its string representation
if isinstance(data, six.string_types):
return str(data.encode('utf-8').decode())
# if this is a list of values, return list of byteified values
if isinstance(data, list):
return [ _byteify(item) for item in data ]
# if this is a dictionary, return dictionary of byteified keys and values
# but only if we haven't already byteified it
if isinstance(data, dict):
return {
_byteify(key): _byteify(value) for key, value in iteritems(data)
}
# if it's anything else, return it in its original form
return data
w = r.json(object_hook=_byteify)
print(w)
반환:
{'three': '', 'key': 'value', 'one': 'two'}
이것은 게임하기에 늦었지만, 나는 이 재귀 캐스터를 만들었다.그것은 내 필요에 맞게 작동하고 나는 그것이 비교적 완전하다고 생각한다.도움이 될지도 모른다.
def _parseJSON(self, obj):
newobj = {}
for key, value in obj.iteritems():
key = str(key)
if isinstance(value, dict):
newobj[key] = self._parseJSON(value)
elif isinstance(value, list):
if key not in newobj:
newobj[key] = []
for i in value:
newobj[key].append(self._parseJSON(i))
elif isinstance(value, unicode):
val = str(value)
if val.isdigit():
val = int(val)
else:
try:
val = float(val)
except ValueError:
val = str(val)
newobj[key] = val
return newobj
그냥 다음과 같은 JSON 개체를 전달하십시오.
obj = json.loads(content, parse_float=float, parse_int=int)
obj = _parseJSON(obj)
나는 그것을 반의 개인회원으로 가지고 있지만, 너는 네가 적합하다고 생각하는 대로 그 방법을 다시 바꿀 수 있어.
나는 wells의 _parse_json()을 다시 써서 json 객체 자체가 배열(나의 사용 사례)인 경우를 처리했다.
def _parseJSON(self, obj):
if isinstance(obj, dict):
newobj = {}
for key, value in obj.iteritems():
key = str(key)
newobj[key] = self._parseJSON(value)
elif isinstance(obj, list):
newobj = []
for value in obj:
newobj.append(self._parseJSON(value))
elif isinstance(obj, unicode):
newobj = str(obj)
else:
newobj = obj
return newobj
여기 C: https://github.com/axiros/nested_encode으로 쓰여진 재귀 인코더가 있다.
json.loads에 비해 "평균" 구조물에 대한 성능 오버헤드.
python speed.py
json loads [0.16sec]: {u'a': [{u'b': [[1, 2, [u'\xd6ster..
json loads + encoding [0.18sec]: {'a': [{'b': [[1, 2, ['\xc3\x96ster.
time overhead in percent: 9%
이 테스트 구조 사용:
import json, nested_encode, time
s = """
{
"firstName": "Jos\\u0301",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "\\u00d6sterreich",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null,
"a": [{"b": [[1, 2, ["\\u00d6sterreich"]]]}]
}
"""
t1 = time.time()
for i in xrange(10000):
u = json.loads(s)
dt_json = time.time() - t1
t1 = time.time()
for i in xrange(10000):
b = nested_encode.encode_nested(json.loads(s))
dt_json_enc = time.time() - t1
print "json loads [%.2fsec]: %s..." % (dt_json, str(u)[:20])
print "json loads + encoding [%.2fsec]: %s..." % (dt_json_enc, str(b)[:20])
print "time overhead in percent: %i%%" % (100 * (dt_json_enc - dt_json)/dt_json)
파이톤 3.6으로, 나는 가끔 여전히 이 문제에 부딪친다.예를 들어, REST API에서 응답을 받고 응답 텍스트를 JSON에 로드할 때, 나는 여전히 유니코드 문자열을 받는다.json.dumps()를 사용하여 간단한 솔루션 발견
response_message = json.loads(json.dumps(response.text))
print(response_message)
나도 이 문제에 부딪혔고, JSON을 처리해야 할 때 유니코드 키를 문자열로 변환하는 작은 루프를 생각해 냈다.(simplejson
GAE에서는 문자열 키를 반환하지 않는다.)
obj
JSON에서 디코딩된 객체:
if NAME_CLASS_MAP.has_key(cls):
kwargs = {}
for i in obj.keys():
kwargs[str(i)] = obj[i]
o = NAME_CLASS_MAP[cls](**kwargs)
o.save()
kwargs
GA 애플리케이션의 생성자에게 전달되는 것(이것은 마음에 들지 않음)unicode
열쇠를 꽂다**kwargs
)
웰스의 솔루션만큼 강력하지는 않지만 훨씬 작다.
나는 마크 아메리의 대답에서 코드를 수정했는데, 특히 그 코드를 없애기 위해서였다.isinstance
오리 사냥의 장점으로
인코딩은 수동으로 수행되며ensure_ascii
장애인이야에 대한 python 문서에는 다음과 같이 적혀 있다.
secure_ascII가 True(기본값)인 경우 ASC가 아닌 모든 항목출력의 II 문자는 \uXXXX 시퀀스로 이스케이프됨
부인: 나는 처음에 헝가리어를 사용했다.헝가리와 관련된 몇몇 주목할 만한 캐릭터 인코딩은 다음과 같다.cp852
DOS에서 사용되는 IBM/OEM 인코딩(때로는 아스키라고 하며, 잘못 생각하지만 코드 페이지 설정에 따라 다름)cp1250
예를 들어 Windows(로케일 설정에 따라 ansi라고도 함)에서 사용됨iso-8859-2
, 때때로 http 서버에서 사용된다.테스트 텍스트Tüskéshátú kígyóbűvölő
콜타이 라즐로(원래 개인 이름 형태)에 기인하고 위키백과에서 유래한다.
# coding: utf-8
"""
This file should be encoded correctly with utf-8.
"""
import json
def encode_items(input, encoding='utf-8'):
u"""original from: https://stackoverflow.com/a/13101776/611007
adapted by SO/u/611007 (20150623)
>>>
>>> ## run this with `python -m doctest <this file>.py` from command line
>>>
>>> txt = u"Tüskéshátú kígyóbűvölő"
>>> txt2 = u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"
>>> txt3 = u"uúuutifu"
>>> txt4 = b'u\\xfauutifu'
>>> # txt4 shouldn't be 'u\\xc3\\xbauutifu', string content needs double backslash for doctest:
>>> assert u'\\u0102' not in b'u\\xfauutifu'.decode('cp1250')
>>> txt4u = txt4.decode('cp1250')
>>> assert txt4u == u'u\\xfauutifu', repr(txt4u)
>>> txt5 = b"u\\xc3\\xbauutifu"
>>> txt5u = txt5.decode('utf-8')
>>> txt6 = u"u\\u251c\\u2551uutifu"
>>> there_and_back_again = lambda t: encode_items(t, encoding='utf-8').decode('utf-8')
>>> assert txt == there_and_back_again(txt)
>>> assert txt == there_and_back_again(txt2)
>>> assert txt3 == there_and_back_again(txt3)
>>> assert txt3.encode('cp852') == there_and_back_again(txt4u).encode('cp852')
>>> assert txt3 == txt4u,(txt3,txt4u)
>>> assert txt3 == there_and_back_again(txt5)
>>> assert txt3 == there_and_back_again(txt5u)
>>> assert txt3 == there_and_back_again(txt4u)
>>> assert txt3.encode('cp1250') == encode_items(txt4, encoding='utf-8')
>>> assert txt3.encode('utf-8') == encode_items(txt5, encoding='utf-8')
>>> assert txt2.encode('utf-8') == encode_items(txt, encoding='utf-8')
>>> assert {'a':txt2.encode('utf-8')} == encode_items({'a':txt}, encoding='utf-8')
>>> assert [txt2.encode('utf-8')] == encode_items([txt], encoding='utf-8')
>>> assert [[txt2.encode('utf-8')]] == encode_items([[txt]], encoding='utf-8')
>>> assert [{'a':txt2.encode('utf-8')}] == encode_items([{'a':txt}], encoding='utf-8')
>>> assert {'b':{'a':txt2.encode('utf-8')}} == encode_items({'b':{'a':txt}}, encoding='utf-8')
"""
try:
input.iteritems
return {encode_items(k): encode_items(v) for (k,v) in input.iteritems()}
except AttributeError:
if isinstance(input, unicode):
return input.encode(encoding)
elif isinstance(input, str):
return input
try:
iter(input)
return [encode_items(e) for e in input]
except TypeError:
return input
def alt_dumps(obj, **kwargs):
"""
>>> alt_dumps({'a': u"T\\u00fcsk\\u00e9sh\\u00e1t\\u00fa k\\u00edgy\\u00f3b\\u0171v\\u00f6l\\u0151"})
'{"a": "T\\xc3\\xbcsk\\xc3\\xa9sh\\xc3\\xa1t\\xc3\\xba k\\xc3\\xadgy\\xc3\\xb3b\\xc5\\xb1v\\xc3\\xb6l\\xc5\\x91"}'
"""
if 'ensure_ascii' in kwargs:
del kwargs['ensure_ascii']
return json.dumps(encode_items(obj), ensure_ascii=False, **kwargs)
JSON 규격을 참조하는 Jarret Hardie의 대답도 다음과 같이 인용하여 강조하고 싶다.
문자열은 0개 이상의 유니코드 문자로 구성된 모음입니다.
나의 사용 사례에서 나는 json과 파일을 가지고 있었다.그들은 그렇다.utf-8
암호화된 파일 ensure_ascii
제대로 빠져나갔지만 잘 읽을 수 있는 json 파일을 만들어내지 못했기 때문에 나는 마크 아메리의 대답을 내 필요에 맞게 수정했다.
가장 좋은 방법은 특별히 사려 깊지 않지만 나는 그것이 누군가에게 유용할 것이라는 희망으로 그 코드를 공유한다.
다음과 같은 유사한 질문에 대한 답을 확인하십시오.
u-prefix는 유니코드 문자열이 있음을 의미한다.문자열을 실제로 사용하면 데이터에 나타나지 않는다.인쇄된 출력물에 속지 마십시오.
예를 들어 다음과 같이 해보십시오.
print mail_accounts[0]["i"]
너는 u를 볼 수 없을 것이다.
참조URL: https://stackoverflow.com/questions/956867/how-to-get-string-objects-instead-of-unicode-from-json
'Programing' 카테고리의 다른 글
vuejs vuex는 돌연변이 없이 2방향 바인딩 상태로 사용(v-model) (0) | 2022.03.28 |
---|---|
오류: 'dct' 개체에 'iteritems' 특성이 없음 " (0) | 2022.03.28 |
하위 구성 요소에서 상위 데이터 업데이트 (0) | 2022.03.28 |
vuetify.js v-property의 전체 너비를 얻는 방법 (0) | 2022.03.28 |
검색되지 않은 TypeError: 정의되지 않은 속성을 읽을 수 없음('_H' 읽기) (0) | 2022.03.28 |