Easiest way to serialize a simple class object with simplejson? Easiest way to serialize a simple class object with simplejson? python python

Easiest way to serialize a simple class object with simplejson?


I've used this strategy in the past and been pretty happy with it: Encode your custom objects as JSON object literals (like Python dicts) with the following structure:

{ '__ClassName__': { ... } }

That's essentially a one-item dict whose single key is a special string that specifies what kind of object is encoded, and whose value is a dict of the instance's attributes. If that makes sense.

A very simple implementation of an encoder and a decoder (simplified from code I've actually used) is like so:

TYPES = { 'ParentClass': ParentClass,          'ChildClass': ChildClass }class CustomTypeEncoder(json.JSONEncoder):    """A custom JSONEncoder class that knows how to encode core custom    objects.    Custom objects are encoded as JSON object literals (ie, dicts) with    one key, '__TypeName__' where 'TypeName' is the actual name of the    type to which the object belongs.  That single key maps to another    object literal which is just the __dict__ of the object encoded."""    def default(self, obj):        if isinstance(obj, TYPES.values()):            key = '__%s__' % obj.__class__.__name__            return { key: obj.__dict__ }        return json.JSONEncoder.default(self, obj)def CustomTypeDecoder(dct):    if len(dct) == 1:        type_name, value = dct.items()[0]        type_name = type_name.strip('_')        if type_name in TYPES:            return TYPES[type_name].from_dict(value)    return dct

In this implementation assumes that the objects you're encoding will have a from_dict() class method that knows how to take recreate an instance from a dict decoded from JSON.

It's easy to expand the encoder and decoder to support custom types (e.g. datetime objects).

EDIT, to answer your edit: The nice thing about an implementation like this is that it will automatically encode and decode instances of any object found in the TYPES mapping. That means that it will automatically handle a ChildClass like so:

class ChildClass(object):    def __init__(self):        self.foo = 'foo'        self.bar = 1.1        self.parent = ParentClass(1)

That should result in JSON something like the following:

{ '__ChildClass__': {    'bar': 1.1,    'foo': 'foo',    'parent': {        '__ParentClass__': {            'foo': 1}        }    }}


An instance of a custom class could be represented as JSON formatted string with help of following function:

def json_repr(obj):  """Represent instance of a class as JSON.  Arguments:  obj -- any object  Return:  String that reprent JSON-encoded object.  """  def serialize(obj):    """Recursively walk object's hierarchy."""    if isinstance(obj, (bool, int, long, float, basestring)):      return obj    elif isinstance(obj, dict):      obj = obj.copy()      for key in obj:        obj[key] = serialize(obj[key])      return obj    elif isinstance(obj, list):      return [serialize(item) for item in obj]    elif isinstance(obj, tuple):      return tuple(serialize([item for item in obj]))    elif hasattr(obj, '__dict__'):      return serialize(obj.__dict__)    else:      return repr(obj) # Don't know how to handle, convert to string  return json.dumps(serialize(obj))

This function will produce JSON-formatted string for

  • an instance of a custom class,

  • a dictionary that have instances ofcustom classes as leaves,

  • a list of instances of customclasses


If you are using Django, it can be easily done via Django's serializers module. More info can be found here: https://docs.djangoproject.com/en/dev/topics/serialization/