[python] 클래스 JSON을 직렬화 가능하게 만드는 방법

파이썬 클래스를 직렬화 가능하게 만드는 방법?

간단한 수업 :

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 백엔드를 선택하고 추가 백엔드를 추가 할 수 있습니다.

(PyPi의 jsonpickle에 링크)


답변

대부분의 대답은 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()프로젝트의 모든 것을 업데이트 할 필요는 없습니다 .