JSON 세트를 시리얼화하는 방법
는 파이썬 파이썬을 있다.set가 포함되어 .__hash__ ★★★★★★★★★★★★★★★★★」__eq__중복이 컬렉션에 포함되지 않도록 하기 위한 메서드입니다.
.set지나가다setjson.dumps은 메 a a a a a a a method를 .TypeError.
File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 178, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: set([]) is not JSON serializable
는 내가 수 것을 .json.JSONEncoder default 「를 잘 set 은 을 해서 만들어 요?set디폴트 메서드 내에서 값을 지정한 후 인코딩을 반환합니다.이상적으로는 디폴트 메서드로 원래 인코더가 체크하는 모든 데이터 타입을 처리할 수 있도록 하고 싶다(Mongo를 데이터 소스로 사용하고 있기 때문에 날짜도 이 에러가 발생하는 것 같다.
올바른 방향으로 힌트를 주시면 감사하겠습니다.
편집:
답변 감사합니다!좀 더 정확하게 말할 걸 그랬나 봐요
이) '어느 정도'라는 한계를 .set번역되고 있습니다만, 내부 키도 문제가 되고 있습니다.
의 set라고 하는 것은, 입니다.__dict__단, json 인코더 내의 기본유형에 적합하지 않을 수 있는 속성값도 포함할 수 있습니다.
들어오고 있어요.set해시는 기본적으로 엔티티에 대한 고유 ID를 계산하지만, 진정한 의미의 NoSQL에서는 하위 객체가 정확히 무엇을 포함하고 있는지 알 수 없습니다.
에는 날짜 수 .starts다른 스키마에는 "비표준" 개체를 포함하는 키가 포함되지 않은 다른 스키마가 있을 수 있습니다.
은 ''밖에.JSONEncoderdefault다른 케이스를 활성화하는 방법 - 하지만 어떻게 해야 할지 잘 모르겠고 문서도 애매합니다.은 첩음음에서 반환되는 입니까?default키별로 이동하거나 개체 전체를 보는 일반적인 포함/부호만 포함합니까?이 방법은 어떻게 중첩된 값을 수용합니까?이전 질문들을 살펴봤지만, 케이스 고유의 인코딩에 대한 최선의 접근방식을 찾을 수 없는 것 같습니다(불행하게도 여기서 해야 할 것 같습니다).
「」를할 수 .list when 를 만났을 때set하다
import json
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return json.JSONEncoder.default(self, obj)
data_str = json.dumps(set([1,2,3,4,5]), cls=SetEncoder)
print(data_str)
# Output: '[1, 2, 3, 4, 5]'
이렇게 하면 다른 종류도 탐지할 수 있습니다.목록이 실제로 세트임을 유지해야 하는 경우 사용자 지정 인코딩을 사용할 수 있습니다.return {'type':'set', 'list':list(obj)}효과가 있을지도 모릅니다.
네스트된 타입을 나타내려면 , 다음의 시리얼화를 검토해 주세요.
class Something(object):
pass
json.dumps(set([1,2,3,4,5,Something()]), cls=SetEncoder)
이것에 의해, 다음의 에러가 발생합니다.
TypeError: <__main__.Something object at 0x1691c50> is not JSON serializable
은, 가 「」, 「」, 「」, 「」, 「」를 을 나타냅니다.list결과가 반환되어 하위의 시리얼라이저를 재귀적으로 호출합니다.여러 유형의 커스텀시리얼라이저를 추가하려면 다음 작업을 수행합니다.
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
if isinstance(obj, Something):
return 'CustomSomethingRepresentation'
return json.JSONEncoder.default(self, obj)
data_str = json.dumps(set([1,2,3,4,5,Something()]), cls=SetEncoder)
print(data_str)
# Output: '[1, 2, 3, 4, 5, "CustomSomethingRepresentation"]'
JSON 표기법에는 네이티브 데이터형(오브젝트, 배열, 문자열, 숫자, 부울 및 늘)이 몇 개밖에 없기 때문에 JSON에서 직렬화된 모든 데이터는 이러한 유형 중 하나로 표현해야 합니다.
json 모듈 문서에 나타나 있듯이 이 변환은 JSONEncoder와 JSONDecoder에 의해 자동으로 수행될 수 있지만, 필요한 다른 구조를 포기하게 됩니다(세트를 목록으로 변환하면 일반 목록을 복구하는 기능이 상실됩니다).dict.fromkeys(s)을 참조해 주십시오.)
보다 정교한 솔루션은 다른 네이티브 JSON 유형과 공존할 수 있는 사용자 지정 유형을 구축하는 것입니다.이를 통해 목록, 세트, 딕트, 소수점, 날짜/시간 개체 등을 포함하는 중첩 구조를 저장할 수 있습니다.
from json import dumps, loads, JSONEncoder, JSONDecoder
import pickle
class PythonObjectEncoder(JSONEncoder):
def default(self, obj):
try:
return {'_python_object': pickle.dumps(obj).decode('latin-1')}
except pickle.PickleError:
return super().default(obj)
def as_python_object(dct):
if '_python_object' in dct:
return pickle.loads(dct['_python_object'].encode('latin-1'))
return dct
다음은 목록, 받아쓰기 및 집합을 처리할 수 있음을 보여주는 샘플 세션입니다.
>>> data = [1,2,3, set(['knights', 'who', 'say', 'ni']), {'key':'value'}, Decimal('3.14')]
>>> j = dumps(data, cls=PythonObjectEncoder)
>>> loads(j, object_hook=as_python_object)
[1, 2, 3, set(['knights', 'say', 'who', 'ni']), {'key': 'value'}, Decimal('3.14')]
또는 YAML, Twisted Jelly 또는 Python의 피클 모듈과 같은 보다 범용적인 시리얼라이제이션 기술을 사용하는 것이 유용할 수 있습니다.이들 각각은 훨씬 광범위한 데이터 유형을 지원합니다.
는 커스텀인코더 를 만들 defaultmethod -인수로 할 수 .
import json
def serialize_sets(obj):
if isinstance(obj, set):
return list(obj)
return obj
json_str = json.dumps(set([1,2,3]), default=serialize_sets)
print(json_str)
이 되다[1, 2, 3]Python은 Python입니다.
할 수 없는 는 「」이라는 있는 .sets, 매우 심플한(더러운) 솔루션이 있습니다.
json.dumps({"Hello World": {1, 2}}, default=tuple)
할 수 됩니다.default 그 중 하나밖에 settuple.
Raymond Hettinger의 솔루션을 python 3에 적용했습니다.
변경된 내용은 다음과 같습니다.
unicode를 감추다- 했다.
defaultsuper() - 를 사용합니다.
base64bytes타이핑하다str(되기 때문에)bytespython 으로 변환할 수 .
from decimal import Decimal
from base64 import b64encode, b64decode
from json import dumps, loads, JSONEncoder
import pickle
class PythonObjectEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, (list, dict, str, int, float, bool, type(None))):
return super().default(obj)
return {'_python_object': b64encode(pickle.dumps(obj)).decode('utf-8')}
def as_python_object(dct):
if '_python_object' in dct:
return pickle.loads(b64decode(dct['_python_object'].encode('utf-8')))
return dct
data = [1,2,3, set(['knights', 'who', 'say', 'ni']), {'key':'value'}, Decimal('3.14')]
j = dumps(data, cls=PythonObjectEncoder)
print(loads(j, object_hook=as_python_object))
# prints: [1, 2, 3, {'knights', 'who', 'say', 'ni'}, {'key': 'value'}, Decimal('3.14')]
퀵 덤프만 필요하고 커스텀 인코더를 실장하고 싶지 않은 경우.다음을 사용할 수 있습니다.
json_string = json.dumps(data, iterable_as_array=True)
이것에 의해, 모든 세트(및 그 외의 반복 가능)가 어레이로 변환됩니다.JSON을 다시 해석할 때 이러한 필드는 어레이 상태로 유지되도록 주의하십시오.유형을 보존하려면 커스텀인코더를 쓸 필요가 있습니다.
꼭 계셔야 합니다.simplejson설치 및 필수입니다.
PyPi에서 찾을 수 있습니다.
JSON에서는 사전, 목록 및 원시 개체 유형(int, string, bool)만 사용할 수 있습니다.
일반적인 Python 객체가 아닌 집합만 인코딩하고 쉽게 사람이 읽을 수 있도록 하려면 Raymond Hettinger의 답변을 단순화한 버전을 사용할 수 있습니다.
import json
import collections
class JSONSetEncoder(json.JSONEncoder):
"""Use with json.dumps to allow Python sets to be encoded to JSON
Example
-------
import json
data = dict(aset=set([1,2,3]))
encoded = json.dumps(data, cls=JSONSetEncoder)
decoded = json.loads(encoded, object_hook=json_as_python_set)
assert data == decoded # Should assert successfully
Any object that is matched by isinstance(obj, collections.Set) will
be encoded, but the decoded value will always be a normal Python set.
"""
def default(self, obj):
if isinstance(obj, collections.Set):
return dict(_set_object=list(obj))
else:
return json.JSONEncoder.default(self, obj)
def json_as_python_set(dct):
"""Decode json {'_set_object': [1,2,3]} to set([1,2,3])
Example
-------
decoded = json.loads(encoded, object_hook=json_as_python_set)
Also see :class:`JSONSetEncoder`
"""
if '_set_object' in dct:
return set(dct['_set_object'])
return dct
@AntiHaapala의 단축판:
json.dumps(dict_with_sets, default=lambda x: list(x) if isinstance(x, set) else x)
>>> import json
>>> set_object = set([1,2,3,4])
>>> json.dumps(list(set_object))
'[1, 2, 3, 4]'
승인된 솔루션의 단점 중 하나는 출력이 매우 비단뱀에 고유하다는 것입니다.즉, raw json 출력을 사람이 관찰하거나 다른 언어(예: javascript)로 로드할 수 없습니다.예:
db = {
"a": [ 44, set((4,5,6)) ],
"b": [ 55, set((4,3,2)) ]
}
j = dumps(db, cls=PythonObjectEncoder)
print(j)
다음과 같은 이점을 얻을 수 있습니다.
{"a": [44, {"_python_object": "gANjYnVpbHRpbnMKc2V0CnEAXXEBKEsESwVLBmWFcQJScQMu"}], "b": [55, {"_python_object": "gANjYnVpbHRpbnMKc2V0CnEAXXEBKEsCSwNLBGWFcQJScQMu"}]}
동일한 인코더를 사용하여 python에 로드했을 때 목록을 포함하는 dict로 세트를 다운그레이드하고 이를 통해 관찰 가능성과 언어 불가지론을 유지하는 솔루션을 제안할 수 있습니다.
from decimal import Decimal
from base64 import b64encode, b64decode
from json import dumps, loads, JSONEncoder
import pickle
class PythonObjectEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, (list, dict, str, int, float, bool, type(None))):
return super().default(obj)
elif isinstance(obj, set):
return {"__set__": list(obj)}
return {'_python_object': b64encode(pickle.dumps(obj)).decode('utf-8')}
def as_python_object(dct):
if '__set__' in dct:
return set(dct['__set__'])
elif '_python_object' in dct:
return pickle.loads(b64decode(dct['_python_object'].encode('utf-8')))
return dct
db = {
"a": [ 44, set((4,5,6)) ],
"b": [ 55, set((4,3,2)) ]
}
j = dumps(db, cls=PythonObjectEncoder)
print(j)
ob = loads(j)
print(ob["a"])
그 결과, 다음과 같습니다.
{"a": [44, {"__set__": [4, 5, 6]}], "b": [55, {"__set__": [2, 3, 4]}]}
[44, {'__set__': [4, 5, 6]}]
키가 있는 요소가 있는 사전을 직렬화하는 데 유의하십시오."__set__"을 사용하다 ★★★★★★★★★★★★★★★★★.__set__ 유보적인 가 되었습니다.dict열쇠요. 분명히 더 깊게 난독화된 다른 키를 사용하셔도 됩니다.
jsonwhything을 시도해 보세요.
https://pypi.org/project/jsonwhatever/
pip install jsonwhaty
from jsonwhatever import JsonWhatEver
set_a = {1,2,3}
jsonwe = JsonWhatEver()
string_res = jsonwe.jsonwhatever('set_string', set_a)
print(string_res)
언급URL : https://stackoverflow.com/questions/8230315/how-to-json-serialize-sets
'source' 카테고리의 다른 글
| "Newtonsoft에서 항목을 추가하거나 제거할 수 없습니다.Json.Linq.JProperty"를 참조해 주세요. (0) | 2023.02.12 |
|---|---|
| React에서 중첩된 모양에 대한 기본 소품을 제공하려면 어떻게 해야 합니까? (0) | 2023.02.12 |
| @PathVariable을 사용한 Spring MVC 주석 컨트롤러 인터페이스 (0) | 2023.02.12 |
| WooCommerce 쿠폰은 데이터베이스에 어떻게 저장됩니까? (0) | 2023.02.12 |
| 각도 각도 조절기 - E2E 테스트 후 브라우저를 열어 둡니다. (0) | 2023.02.08 |