파이썬 클래스를 직렬화 가능하게 만드는 방법?
간단한 수업 :
class FileItem:
def __init__(self, fname):
self.fname = fname
출력을 얻으려면 어떻게해야합니까?
>>> import json
>>> my_file = FileItem('/foo/bar')
>>> json.dumps(my_file)
TypeError: Object of type 'FileItem' is not JSON serializable
오류없이
답변
예상 출력에 대한 아이디어가 있습니까? 예를 들어 이렇게합니까?
>>> f = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'
이 경우에는을 호출하기 만하면 json.dumps(f.__dict__)
됩니다.
더 많은 사용자 정의 출력을 원하면 JSONEncoder
자체 사용자 정의 직렬화 를 서브 클래스 화 하고 구현해야합니다.
간단한 예는 아래를 참조하십시오.
>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'
그런 다음이 클래스를 kwarg 로 json.dumps()
메소드에 전달하십시오 cls
.
json.dumps(cls=MyEncoder)
또한 디코딩 object_hook
하려면 JSONDecoder
클래스에 사용자 정의 를 제공해야 합니다. 예를 들어
>>> def from_json(json_object):
if 'fname' in json_object:
return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>>
답변
간단한 기능에 대한 간단한 솔루션은 다음과 같습니다.
.toJSON()
방법
JSON 직렬화 가능 클래스 대신 직렬화 기 메소드를 구현하십시오.
import json
class Object:
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
그래서 당신은 그것을 직렬화하기 위해 그것을 부릅니다.
me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"
print(me.toJSON())
출력합니다 :
{
"age": 35,
"dog": {
"name": "Apollo"
},
"name": "Onur"
}
답변
더 복잡한 클래스의 경우 jsonpickle 도구를 고려할 수 있습니다 .
jsonpickle은 복잡한 Python 객체를 JSON과 직렬화 및 역 직렬화하는 Python 라이브러리입니다.
stdlib의 json, simplejson 및 demjson과 같이 JSON을 Python으로 인코딩하기위한 표준 Python 라이브러리는 JSON과 직접적으로 동일한 Python 기본 체 (예 : dicts, list, strings, ints 등) 만 처리 할 수 있습니다. jsonpickle은 이러한 라이브러리 위에 빌드되며보다 복잡한 데이터 구조를 JSON으로 직렬화 할 수 있습니다. jsonpickle은 구성 및 확장 성이 뛰어나 사용자가 JSON 백엔드를 선택하고 추가 백엔드를 추가 할 수 있습니다.
답변
대부분의 대답은 json.dumps () 호출을 변경하는 것과 관련 이 있으며 항상 가능하거나 바람직하지는 않습니다 (예 : 프레임 워크 구성 요소 내부에서 발생할 수 있음).
json.dumps (obj)를있는 그대로 호출 하려면 간단한 솔루션이 dict 에서 상속됩니다 .
class FileItem(dict):
def __init__(self, fname):
dict.__init__(self, fname=fname)
f = FileItem('tasks.txt')
json.dumps(f) #No need to change anything here
이것은 클래스가 기본 데이터 표현 일 경우 작동합니다. 까다로운 작업으로 항상 키를 명시 적으로 설정할 수 있습니다.
답변
Onur의 답변이 마음에 들지만 toJSON()
객체를 직렬화 하는 선택적 방법 을 포함하도록 확장 합니다.
def dumper(obj):
try:
return obj.toJSON()
except:
return obj.__dict__
print json.dumps(some_big_object, default=dumper, indent=2)
답변
또 다른 옵션은 JSON 덤프를 자체 클래스로 래핑하는 것입니다.
import json
class FileItem:
def __init__(self, fname):
self.fname = fname
def __repr__(self):
return json.dumps(self.__dict__)
또는 클래스에서 FileItem 클래스를 서브 클래 싱하는 것이 더 좋습니다 JsonSerializable
.
import json
class JsonSerializable(object):
def toJson(self):
return json.dumps(self.__dict__)
def __repr__(self):
return self.toJson()
class FileItem(JsonSerializable):
def __init__(self, fname):
self.fname = fname
테스트 :
>>> f = FileItem('/foo/bar')
>>> f.toJson()
'{"fname": "/foo/bar"}'
>>> f
'{"fname": "/foo/bar"}'
>>> str(f) # string coercion
'{"fname": "/foo/bar"}'
답변
to_json
다음과 같이 클래스 에 메소드를 추가 하십시오.
def to_json(self):
return self.message # or how you want it to be serialized
그리고이 코드 ( 이 답변에서 ) 를 맨 위에 어딘가에 추가하십시오 .
from json import JSONEncoder
def _default(self, obj):
return getattr(obj.__class__, "to_json", _default.default)(obj)
_default.default = JSONEncoder().default
JSONEncoder.default = _default
JSONEncoder.default ()가 자동으로 특수한 “to_json ()”메소드를 확인하고 발견 된 경우이를 사용하여 JSON 모듈을 가져 오면 원숭이 패치를 원숭이 패치합니다.
Onur가 말했듯이 이번에는 json.dumps()
프로젝트의 모든 것을 업데이트 할 필요는 없습니다 .