source

클래스 JSON을 시리얼화 하는 방법

manycodes 2022. 12. 25. 09:43
반응형

클래스 JSON을 시리얼화 하는 방법

Python 클래스를 직렬화하려면 어떻게 해야 합니까?

class FileItem:
    def __init__(self, fname):
        self.fname = fname

JSON에 직렬화 시도:

>>> import json
>>> x = FileItem('/foo/bar')
>>> json.dumps(x)
TypeError: Object of type 'FileItem' is not JSON serializable

다음은 간단한 기능을 위한 간단한 솔루션입니다.

.toJSON() ★★★

JSON serializable 클래스 대신 serializer 메서드를 구현합니다.

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"
}

예상 생산량에 대해 알고 계십니까?예를 들어, 이것으로 충분할까요?

>>> f  = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'

는 그냥 요.json.dumps(f.__dict__)

보다 커스터마이즈된 출력을 필요로 하는 경우는, 독자적인 커스텀 시리얼화를 서브 클래스 해 실장할 필요가 있습니다.

간단한 예에 대해서는, 이하를 참조해 주세요.

>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
        def default(self, o):
            return o.__dict__    

>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'

그런 다음 이 클래스를 메서드에 전달합니다.cls 삭제:

json.dumps(cls=MyEncoder)

디코딩을 하려면 커스텀을 입력해야 합니다.object_hook학급에.예를 들어 다음과 같습니다.

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

보다 복잡한 클래스의 경우 도구 jsonpickle을 고려할 수 있습니다.

jsonpickle은 JSON과 주고받는 복잡한 Python 객체를 직렬화 및 직렬화 해제하기 위한 Python 라이브러리입니다.

stdlib의 json, simplejson 및 demjson과 같이 Python을 JSON으로 인코딩하기 위한 표준 Python 라이브러리는 직접적인 JSON 상당(dicts, lists, string, int 등)을 가진 Python 프리미티브만 처리할 수 있습니다.json pickle은 이러한 라이브러리 위에 구축되어 JSon을 직렬화할 수 있습니다.ghly 설정 및 확장 가능 - 사용자가 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

이 기능은 클래스가 기본 데이터 표현일 경우 작동하며, 보다 까다로운 작업에는 항상 키를 명시적으로 설정할 수 있습니다.

했듯이, 여러분은 을 '하다'에게 수 있습니다.json.dumps기본적으로 지원되지 않는 개체를 지원되는 유형으로 변환합니다.의외로 이들 중 가장 간단한 경우를 언급하는 것은 없습니다.즉, 빌트인 함수를 사용하여 객체를 모든 속성을 포함하는 딕트로 변환하는 것입니다.

json.dumps(obj, default=vars)

등 보다 , Atribute가는, 것에 해 주세요.__dict__ Atribute를 해야 .JSONEncoder른른른

더하면 돼요.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

Import 됩니다.따라서 Import는 monkey-patch는 monkey-patch입니다.JSONEncoder.default()는, 한 「」를 으로 합니다.to_json()방법

오누르가 말한 처럼, 하지만 이번엔 매번 업데이트 할 필요는 없어json.dumps()를 참조해 주세요.

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

파일 를 하위 분류하는 도 좋습니다.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"}'

Python 3.5+를 사용하고 있다면 를 사용할 수 있습니다.( PyPi : https://pypi.org/project/jsons/)오브젝트(및 오브젝트의 모든 속성)를 dict로 재귀적으로 변환합니다.

import jsons

a_dict = jsons.dump(your_object)

또는 문자열을 원하는 경우:

a_str = jsons.dumps(your_object)

당신의 클래스가 「」를 실장하고 있는 .jsons.JsonSerializable:

a_dict = your_object.json

며칠 전에 이 문제를 발견하고 중첩개체와 상속된 필드를 처리할 수 있는 보다 일반적인 버전의 Python용 인코더 개체를 구현했습니다.

import json
import inspect

class ObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_json"):
            return self.default(obj.to_json())
        elif hasattr(obj, "__dict__"):
            d = dict(
                (key, value)
                for key, value in inspect.getmembers(obj)
                if not key.startswith("__")
                and not inspect.isabstract(value)
                and not inspect.isbuiltin(value)
                and not inspect.isfunction(value)
                and not inspect.isgenerator(value)
                and not inspect.isgeneratorfunction(value)
                and not inspect.ismethod(value)
                and not inspect.ismethoddescriptor(value)
                and not inspect.isroutine(value)
            )
            return self.default(d)
        return obj

예:

class C(object):
    c = "NO"
    def to_json(self):
        return {"c": "YES"}

class B(object):
    b = "B"
    i = "I"
    def __init__(self, y):
        self.y = y
        
    def f(self):
        print "f"

class A(B):
    a = "A"
    def __init__(self):
        self.b = [{"ab": B("y")}]
        self.c = C()

print json.dumps(A(), cls=ObjectEncoder, indent=2, sort_keys=True)

결과:

{
  "a": "A", 
  "b": [
    {
      "ab": {
        "b": "B", 
        "i": "I", 
        "y": "y"
      }
    }
  ], 
  "c": {
    "c": "YES"
  }, 
  "i": "I"
}

은 다음과 같습니다.
만들기json work your 。

AKA, 결:json.dumps({ "thing": YOUR_CLASS() })


TLDR: 복사 붙여넣기 옵션1 또는 다음 옵션2

설명:

  • 네, 신뢰할 수 있는 솔루션이 존재합니다.
  • 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀, 비단뱀.
    • 해결 방법이라고 (현재) 수 은 없습니다.toJSONJavaScript) / json json jon son java java java java java java java java java java java java java 。그런 일이 있을 때json.dumps([1,2, your_obj])실행되면 python은 룩업 테이블이나 오브젝트 메서드를 체크하지 않습니다.
    • 왜 다른 답이 이걸 설명해주지 않는지 모르겠다.
    • 가장 가까운 공식 접근법은 아마도 사전에서 물려받은 앤디하싯의 대답일 것이다.그러나 AdvancedDateTime 또는 pytorch 텐서와 같은 많은 사용자 지정 클래스에서는 사전에서 상속하는 것이 잘 작동하지 않습니다.
  • 이상적인 회피책은 다음과 같습니다.
    • " " "json.dumps을 미칩니다) (json "Import" pip "는 모든 곳에 영향을 줍니다)
    • def __json__(self) your class (

옵션 1: 모듈에게 패치 적용 실행


pip install json-fix
(팬시존의 답변 확장판+패키지판, 감사합니다@FancyJohn)

your_class_definition.py

import json_fix

class YOUR_CLASS:
    def __json__(self):
        # YOUR CUSTOM CODE HERE
        #    you probably just want to do:
        #        return self.__dict__
        return "a built-in object that is naturally json-able"

바로 그거야.
「 」:

from your_class_definition import YOUR_CLASS
import json

json.dumps([1,2, YOUR_CLASS()], indent=0)
# '[\n1,\n2,\n"a built-in object that is naturally json-able"\n]'

떻게게작?작 동??를를를 2 를를 。

★★★★★★★★★★★★★★★★★를 만들다json.dumpsNumpy 어레이, Panda DataFrames 및 기타 타사 개체에 대해서는 모듈을 참조하십시오(코드의 최대 2줄만 설명 필요).

옵션 2: json.dumps를 직접 패치합니다.

참고: 이 접근 방식은 단순하며 외부 클래스(numpy array, datetime, 데이터 프레임, 텐서 등)의 json 동작을 제어할 수 없습니다.

some_file_class_definitions_your_class_definitions.화이

# Step: 1
# create the patch
from json import JSONEncoder
def wrapped_default(self, obj):
    return getattr(obj.__class__, "__json__", wrapped_default.default)(obj)
wrapped_default.default = JSONEncoder().default
   
# apply the patch
JSONEncoder.original_default = JSONEncoder.default
JSONEncoder.default = wrapped_default

your_class_definition을 지정합니다.화이

# Step 2
class YOUR_CLASS:
    def __json__(self, **options):
        # YOUR CUSTOM CODE HERE
        #    you probably just want to do:
        #        return self.__dict__
        return "a built-in object that is natually json-able"

_

다른 답변은 모두 "커스텀 오브젝트를 시리얼화하기 위한 베스트 프랙티스/접근법"인 것 같습니다.

이는 문서(복잡한 번호의 인코딩 예에 대해서는 "복잡한" 검색)에서 이미 설명되어 있습니다.

import simplejson

class User(object):
    def __init__(self, name, mail):
        self.name = name
        self.mail = mail

    def _asdict(self):
        return self.__dict__

print(simplejson.dumps(User('alice', 'alice@mail.com')))

'''를 json 을가 있습니다.default

import json
def default(o):
    return o._asdict()

print(json.dumps(User('alice', 'alice@mail.com'), default=default))

json 가능한 오브젝트가 .jsonpickle도 있습니다.pip install jsonpickle수 이 있습니다는 텍스트를 들여쓸 수 없는 용어에 제한이 있습니다.클래스를 변경할 수 없는 객체의 내용을 검사하려면 다음 방법보다 더 정확한 방법을 찾을 수 없습니다.

 import json
 import jsonpickle
 ...
 print  json.dumps(json.loads(jsonpickle.encode(object)), indent=2)

주의: 여전히 오브젝트 메서드를 인쇄할 수 없습니다.

【3】
이는 트리와 같은 python 개체에 대한 명시적인 json 직렬화를 보여줍니다.
주의: 실제로 이와 같은 코드를 원하는 경우 트위스트 FilePath 클래스를 사용할 수 있습니다.

import json, sys, os

class File:
    def __init__(self, path):
        self.path = path

    def isdir(self):
        return os.path.isdir(self.path)

    def isfile(self):
        return os.path.isfile(self.path)

    def children(self):        
        return [File(os.path.join(self.path, f)) 
                for f in os.listdir(self.path)]

    def getsize(self):        
        return os.path.getsize(self.path)

    def getModificationTime(self):
        return os.path.getmtime(self.path)

def _default(o):
    d = {}
    d['path'] = o.path
    d['isFile'] = o.isfile()
    d['isDir'] = o.isdir()
    d['mtime'] = int(o.getModificationTime())
    d['size'] = o.getsize() if o.isfile() else 0
    if o.isdir(): d['children'] = o.children()
    return d

folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)

이 클래스는 오브젝트를 standard json으로 변환할 수 있습니다.

import json


class Serializer(object):
    @staticmethod
    def serialize(object):
        return json.dumps(object, default=lambda o: o.__dict__.values()[0])

사용방법:

Serializer.serialize(my_object)

in in in 에서 일하다python2.7 ★★★★★★★★★★★★★★★★★」python3.

import json

class Foo(object):
    def __init__(self):
        self.bar = 'baz'
        self._qux = 'flub'

    def somemethod(self):
        pass

def default(instance):
    return {k: v
            for k, v in vars(instance).items()
            if not str(k).startswith('_')}

json_foo = json.dumps(Foo(), default=default)
assert '{"bar": "baz"}' == json_foo

print(json_foo)

jaraco는 꽤 깔끔한 대답을 했다.몇 가지 사소한 것들을 고쳐야 했지만, 이 방법은 효과가 있었다.

코드

# Your custom class
class MyCustom(object):
    def __json__(self):
        return {
            'a': self.a,
            'b': self.b,
            '__python__': 'mymodule.submodule:MyCustom.from_json',
        }

    to_json = __json__  # supported by simplejson

    @classmethod
    def from_json(cls, json):
        obj = cls()
        obj.a = json['a']
        obj.b = json['b']
        return obj

# Dumping and loading
import simplejson

obj = MyCustom()
obj.a = 3
obj.b = 4

json = simplejson.dumps(obj, for_json=True)

# Two-step loading
obj2_dict = simplejson.loads(json)
obj2 = MyCustom.from_json(obj2_dict)

# Make sure we have the correct thing
assert isinstance(obj2, MyCustom)
assert obj2.__dict__ == obj.__dict__

로딩에는 2단계가 필요합니다.이제 금 으 for now는,서?__python__속성이 사용되지 않습니다.속성은 사용되지 않습니다.

얼마나 흔한 일인가요?

AlJohri 방법을 사용하여 접근법의 인기를 확인합니다.

시리얼화(Python -> JSON):

역직렬화(JSON -> Python):

이것은 나에게 있어서 좋은 결과입니다.

class JsonSerializable(object):

    def serialize(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return self.serialize()

    @staticmethod
    def dumper(obj):
        if "serialize" in dir(obj):
            return obj.serialize()

        return obj.__dict__

그리고 나서.

class FileItem(JsonSerializable):
    ...

그리고.

log.debug(json.dumps(<my object>, default=JsonSerializable.dumper, indent=2))

패키지의 인스톨에 문제가 없는 경우는, 다음의 json-tricks 를 사용할 수 있습니다.

pip install json-tricks

import 그 가져오기 면 가져오기 니 다 됩)를 가져오셔야 합니다.dump(s)부에서json_tricksjson 대신에, 보통 일을 할 것입니다.보통 효과가 있습니다.

from json_tricks import dumps
json_str = dumps(cls_instance, indent=4)

그렇게 되면

{
        "__instance_type__": [
                "module_name.test_class",
                "MyTestCls"
        ],
        "attributes": {
                "attr": "val",
                "dct_attr": {
                        "hello": 42
                }
        }
}

그게 다예요!


이것은 일반적으로 매우 효과적일 것입니다. 가지 예외가. 이 일어나면요. 예를 들어, 에서 특별한 일이 발생할 수 있습니다.__new__

로딩도 확실히 기능합니다(그렇지 않으면 의미가 없습니다).

from json_tricks import loads
json_str = loads(json_str)

은 '아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아'라고 가정합니다.module_name.test_class.MyTestCls가져올 수 있으며 호환되지 않는 방식으로 변경되지 않았습니다.어떤 사전 같은 게 아니라 인스턴스 하나를 돌려받을 거고, 당신이 버린 것과 똑같은 복사본이어야 해요.

연속화(비연속화) 방법을 사용자 정의하려면 다음과 같이 클래스에 특수 메서드를 추가할 수 있습니다.

class CustomEncodeCls:
        def __init__(self):
                self.relevant = 42
                self.irrelevant = 37

        def __json_encode__(self):
                # should return primitive, serializable types like dict, list, int, string, float...
                return {'relevant': self.relevant}

        def __json_decode__(self, **attrs):
                # should initialize all properties; note that __init__ is not called implicitly
                self.relevant = attrs['relevant']
                self.irrelevant = 12

예를 들어 Atribut 파라미터의 일부만 시리얼화합니다.

또한 무료 보너스로 numpy 어레이, 날짜 및 시간, 주문된 맵의 시리얼화 및 json에 코멘트를 포함할 수 있습니다.

면책사항:당신과 같은 문제가 있었기 때문에 json_tricks를 만들었습니다.

Kyle Delaney의 코멘트가 정확하기 때문에 https://stackoverflow.com/a/15538391/1497139과 https://stackoverflow.com/a/10254820/1497139의 개량판을 사용하려고 했습니다.

'JSONAble' 믹스인을 만듭니다.

클래스 JSON을 시리얼라이즈 할 수 있도록 하려면 , 「JSONABLE」을 슈퍼 클래스로 사용해, 다음의 어느쪽인가를 호출합니다.

 instance.toJSON()

또는

 instance.asJSON()

두 가지 방법이 있습니다.JSONAble 클래스를 여기서 제공하는 다른 접근법으로 확장할 수도 있습니다.

가족 및 인물을 사용한 단위 테스트 샘플의 검정 예제는 다음과 같습니다.

toJSOn():

{
    "members": {
        "Flintstone,Fred": {
            "firstName": "Fred",
            "lastName": "Flintstone"
        },
        "Flintstone,Wilma": {
            "firstName": "Wilma",
            "lastName": "Flintstone"
        }
    },
    "name": "The Flintstones"
}

asJSOn():

{'name': 'The Flintstones', 'members': {'Flintstone,Fred': {'firstName': 'Fred', 'lastName': 'Flintstone'}, 'Flintstone,Wilma': {'firstName': 'Wilma', 'lastName': 'Flintstone'}}}

가족 및 개인 샘플에 의한 단위 테스트

def testJsonAble(self):
        family=Family("The Flintstones")
        family.add(Person("Fred","Flintstone")) 
        family.add(Person("Wilma","Flintstone"))
        json1=family.toJSON()
        json2=family.asJSON()
        print(json1)
        print(json2)

class Family(JSONAble):
    def __init__(self,name):
        self.name=name
        self.members={}
    
    def add(self,person):
        self.members[person.lastName+","+person.firstName]=person

class Person(JSONAble):
    def __init__(self,firstName,lastName):
        self.firstName=firstName;
        self.lastName=lastName;

jsonable.py 정의 JSONAble 믹스인

 '''
Created on 2020-09-03

@author: wf
'''
import json

class JSONAble(object):
    '''
    mixin to allow classes to be JSON serializable see
    https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable
    '''

    def __init__(self):
        '''
        Constructor
        '''
    
    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, 
            sort_keys=True, indent=4)
        
    def getValue(self,v):
        if (hasattr(v, "asJSON")):
            return v.asJSON()
        elif type(v) is dict:
            return self.reprDict(v)
        elif type(v) is list:
            vlist=[]
            for vitem in v:
                vlist.append(self.getValue(vitem))
            return vlist
        else:   
            return v
    
    def reprDict(self,srcDict):
        '''
        get my dict elements
        '''
        d = dict()
        for a, v in srcDict.items():
            d[a]=self.getValue(v)
        return d
    
    def asJSON(self):
        '''
        recursively return my dict elements
        '''
        return self.reprDict(self.__dict__)   

이러한 접근방식은 https://pypi.org/project/pylodstorage/에서 이용할 수 있는 https://github.com/WolfgangFahl/pyLoDStorage 프로젝트에 통합되었습니다.

jsonweb이 저에게 가장 좋은 솔루션인 것 같습니다.http://www.jsonweb.info/en/latest/ 를 참조해 주세요.

from jsonweb.encode import to_object, dumper

@to_object()
class DataModel(object):
  def __init__(self, id, value):
   self.id = id
   self.value = value

>>> data = DataModel(5, "foo")
>>> dumper(data)
'{"__type__": "DataModel", "id": 5, "value": "foo"}'
class DObject(json.JSONEncoder):
    def delete_not_related_keys(self, _dict):
        for key in ["skipkeys", "ensure_ascii", "check_circular", "allow_nan", "sort_keys", "indent"]:
            try:
                del _dict[key]
            except:
                continue

    def default(self, o):
        if hasattr(o, '__dict__'):
            my_dict = o.__dict__.copy()
            self.delete_not_related_keys(my_dict)
            return my_dict
        else:
            return o

a = DObject()
a.name = 'abdul wahid'
b = DObject()
b.name = a

print(json.dumps(b, cls=DObject))

Quinten Cabo답변바탕으로 합니다.

def sterilize(obj):
    """Make an object more ameniable to dumping as json
    """
    if type(obj) in (str, float, int, bool, type(None)):
        return obj
    elif isinstance(obj, dict):
        return {k: sterilize(v) for k, v in obj.items()}
    list_ret = []
    dict_ret = {}
    for a in dir(obj):
        if a == '__iter__' and callable(obj.__iter__):
            list_ret.extend([sterilize(v) for v in obj])
        elif a == '__dict__':
            dict_ret.update({k: sterilize(v) for k, v in obj.__dict__.items() if k not in ['__module__', '__dict__', '__weakref__', '__doc__']})
        elif a not in ['__doc__', '__module__']:
            aval = getattr(obj, a)
            if type(aval) in (str, float, int, bool, type(None)):
                dict_ret[a] = aval
            elif a != '__class__' and a != '__objclass__' and isinstance(aval, type):
                dict_ret[a] = sterilize(aval)
    if len(list_ret) == 0:
        if len(dict_ret) == 0:
            return repr(obj)
        return dict_ret
    else:
        if len(dict_ret) == 0:
            return list_ret
    return (list_ret, dict_ret)

차이점은

  1. '반복'이 아니라 '이 가능한 모든 경우에 따라서는 동작합니다.list ★★★★★★★★★★★★★★★★★」tuple(NumPy ★★★★★★★★★★★)
  2. 유형 유형(동적 유형( 유형)(동적 유형 ))에 대해 합니다.__dict__를 참조해 주세요.
  3. 타입 「」을 포함합니다.float ★★★★★★★★★★★★★★★★★」None★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
  4. 「」가 있는 __dict__멤버는 주로 일을 합니다(만약__dict__멤버명이 충돌하면1개밖에 표시되지 않습니다(멤버일 가능성이 높습니다).
  5. 리스트이며 멤버가 있는 클래스는 리스트와 사전의 태플처럼 보입니다.
  6. 그 Python3 (그)))isinstance()변경할 필요가 있는 것은 전화뿐일 수 있습니다.)

이 11년 된 화재에 또 다른 통나무를 던지려면 다음 기준을 충족하는 솔루션을 원합니다.

  • 를 FileItem만 할 수 .json.dumps(obj)
  • FileItem 인스턴스에 fileItem 속성을 지정할 수 있습니다.이름
  • 을 사용하여 에 지정할 수 .json.dumps(obj)
  • 됩니다.json.dumps처럼) ('커스텀시리얼라이저처럼)

IE:

fileItem = FileItem('filename.ext')
assert json.dumps(fileItem) == '{"fname": "filename.ext"}'
assert fileItem.fname == 'filename.ext'

솔루션은 다음과 같습니다.

  • 을 obj에게 .dict
  • .dict
class FileItem(dict):
    def __init__(self, fname):
        self['fname'] = fname

    #fname property
    fname: str = property()
    @fname.getter
    def fname(self):
        return self['fname']

    @fname.setter
    def fname(self, value: str):
        self['fname'] = value

    #Repeat for other properties

네, 많은 속성이 있는 경우에는 다소 긴 감기가 있지만 JSON Serializable이 가능하며 오브젝트처럼 동작합니다.이것에 의해, 어느 라이브러리에도 액세스 할 수 있습니다.json.dumps(obj)바로 그거에요.

왜 이렇게 복잡하게 만드세요?다음으로 간단한 예를 제시하겠습니다.

#!/usr/bin/env python3

import json
from dataclasses import dataclass

@dataclass
class Person:
    first: str
    last: str
    age: int

    @property
    def __json__(self):
        return {
            "name": f"{self.first} {self.last}",
            "age": self.age
        }

john = Person("John", "Doe", 42)
print(json.dumps(john, indent=4, default=lambda x: x.__json__))

클래스를 .__json__비단뱀 no no no 、 no 、 no 、 no 、 no 、 no 、 no no no 。JSONEncoder,default단순 람다를 사용하는 매개 변수도 올바르게 작동합니다.

가 쓴 적이 있어요.@property단순한 기능보다는 좀 더 자연스럽고 모던한 느낌이에요.@dataclass에서도 사용할 수, 수, 예, 예, 예,예, 예, 예, '보통' 클래스에서도 할 수 .

나는 로스트 코더의 방식이 가장 마음에 들었다.멤버/메서드를 직렬화할 수 없는 더 복잡한 개체를 직렬화할 때 문제가 발생했습니다.다음은 더 많은 개체에서 작동하는 구현입니다.

class Serializer(object):
    @staticmethod
    def serialize(obj):
        def check(o):
            for k, v in o.__dict__.items():
                try:
                    _ = json.dumps(v)
                    o.__dict__[k] = v
                except TypeError:
                    o.__dict__[k] = str(v)
            return o
        return json.dumps(check(obj).__dict__, indent=2)

Peee pe 、 Postgre pe 、 Postgre pe pe pe pe pe 。SQLJSONField.

한동안 고군분투한 끝에 일반적인 해결책이 여기 있습니다.

내 솔루션의 핵심은 Python의 소스 코드를 살펴보고 코드 문서(여기 설명됨)가 기존 코드를 확장하는 방법을 이미 설명한다는 것을 깨닫는 것입니다.json.dumps하다

현재 JSON에 대해 직렬화할 수 없는 일부 필드를 포함하는 모델이 있고 JSON 필드를 포함하는 모델은 원래 다음과 같습니다.

class SomeClass(Model):
    json_field = JSONField()

커스텀을 .JSONEncoder음음음같 뭇매하다

class CustomJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, SomeTypeUnsupportedByJsonDumps):
            return < whatever value you want >
        return json.JSONEncoder.default(self, obj)

    @staticmethod
    def json_dumper(obj):
        return json.dumps(obj, cls=CustomJsonEncoder)

에 그냥 '아예'에요.JSONField음음음같 뭇매하다

class SomeClass(Model):
    json_field = JSONField(dumps=CustomJsonEncoder.json_dumper)

는 「」입니다.default(self, obj)★★★★★★★마다 1★★★★★... is not JSON serializablePython에서 불만 Python 등을하는 코드를 하는 것 입니다.Enum ★★★★★★★★★★★★★★★★★」datetime)

예를 들어, 다음에서 상속되는 클래스를 지원하는 방법은 다음과 같습니다.Enum:

class TransactionType(Enum):
   CURRENT = 1
   STACKED = 2

   def default(self, obj):
       if isinstance(obj, TransactionType):
           return obj.value
       return json.JSONEncoder.default(self, obj)

마지막으로 위와 같이 구현된 코드를 사용하여 Peeee 모델을 다음과 같이 JSON-seriazable 객체로 변환할 수 있습니다.

peewee_model = WhateverPeeweeModel()
new_model = SomeClass()
new_model.json_field = model_to_dict(peewee_model)

위의 코드는 Peeee에게만 해당되는 것이지만, 저는 다음과 같이 생각합니다.

  1. 일반적으로 다른 ORM(장고 등)에 적용할 수 있습니다.
  2. 어떻게 아는지 알 수 있어요.json.dumpsPython ORM합니다.

질문 있으시면 댓글로 올려주세요.감사합니다!

먼저 표준 JSON 모듈을 사용하여 덤프할 수 있도록 객체를 JSON에 준거해야 합니다.나는 이렇게 했다:

def serialize(o):
    if isinstance(o, dict):
        return {k:serialize(v) for k,v in o.items()}
    if isinstance(o, list):
        return [serialize(e) for e in o]
    if isinstance(o, bytes):
        return o.decode("utf-8")
    return o

이 함수는 재귀를 사용하여 사전의 모든 부분에 걸쳐 반복한 후 빌트인 유형이 아닌 클래스의 repr() 메서드를 호출합니다.

def sterilize(obj):
    object_type = type(obj)
    if isinstance(obj, dict):
        return {k: sterilize(v) for k, v in obj.items()}
    elif object_type in (list, tuple):
        return [sterilize(v) for v in obj]
    elif object_type in (str, int, bool, float):
        return obj
    else:
        return obj.__repr__()

나는 나만의 해결책을 생각해 냈다.이 방법을 사용하여 일련화할 문서(dict, list, ObjectId 등)를 전달합니다.

def getSerializable(doc):
    # check if it's a list
    if isinstance(doc, list):
        for i, val in enumerate(doc):
            doc[i] = getSerializable(doc[i])
        return doc

    # check if it's a dict
    if isinstance(doc, dict):
        for key in doc.keys():
            doc[key] = getSerializable(doc[key])
        return doc

    # Process ObjectId
    if isinstance(doc, ObjectId):
        doc = str(doc)
        return doc

    # Use any other custom serializting stuff here...

    # For the rest of stuff
    return doc

언급URL : https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable

반응형