How to make simplejson serializable class

后端 未结 2 1097
傲寒
傲寒 2020-12-30 12:57

I have a class defined like this

class A:
    def __init__(self):
        self.item1 = None
    def __repr__(self):
        return str(self.__dict__)
         


        
相关标签:
2条回答
  • 2020-12-30 13:30

    According to the json module docs (simplejson was adopted as json in Python 2.6), you need to extend the json.JSONEncoder class, overriding its default method to translate your object into a type that can be serialised. There doesn't appear to be a method that it looks for on your object.

    0 讨论(0)
  • 2020-12-30 13:39

    You can't serialize arbitrary objects with simplejson. You need to pass a default and object_hook to dump and load. Here's an example:

    class SerializerRegistry(object):
        def __init__(self):
            self._classes = {}
        def add(self, cls):
            self._classes[cls.__module__, cls.__name__] = cls
            return cls
        def object_hook(self, dct):
            module, cls_name = dct.pop('__type__', (None, None))
            if cls_name is not None:
                return self._classes[module, cls_name].from_dict(dct)
            else:
                return dct
        def default(self, obj):
            dct = obj.to_dict()
            dct['__type__'] = [type(obj).__module__,
                               type(obj).__name__]
            return dct
    
    registry = SerializerRegistry()
    
    @registry.add
    class A(object):
        def __init__(self, item1):
            self.item1 = item1
        def __repr__(self):
            return str(self.__dict__)
        def to_dict(self):
            return dict(item1=self.item1)
        @classmethod
        def from_dict(cls, dct):
            return cls(**dct)
    
    s = json.dumps(A(1), default=registry.default)
    a = json.loads(s, object_hook=registry.object_hook)
    

    This results in this:

    >>> s
    '{"item1": 1, "__type__": ["__main__", "A"]}'
    >>> a
    {'item1': 1}
    

    But what you really need is a function default that creates dictionary from the objects that you wish to serialize, and a function object_hook that returns an object (of the correct type) when it is given a dictionary if a dictionary isn't enough. The best approach is to have methods on the serializable classes that create a dict from the object and that construct it back, and also to have a mapping that recognizes to which class the dictionaries belong.

    You can also add an identifier to the classes to be used as an index for _classes. This way you wouldn't have issues if you have to move a class.

    0 讨论(0)
提交回复
热议问题