我之前使用过这种策略,并且非常满意:将您的自定义对象编码为JSON对象文字(类似于Python中的dict
),具有以下结构:
{ '__ClassName__': { ... } }
这本质上是一个只有一个项的dict
,其单个键是指定编码对象类型的特殊字符串,其值是实例属性的dict
。如果这样说有意义的话。
一个非常简单的编码器和解码器实现(从我实际使用的代码简化而来)如下:
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
在这个实现中,假设你要编码的对象将拥有一个
from_dict()
类方法,它知道如何从从JSON解码的
dict
中重新创建一个实例。
很容易扩展编码器和解码器以支持自定义类型(例如
datetime
对象)。
编辑,以回答您的编辑:这样实现的好处是它将自动编码和解码在
TYPES
映射中找到的任何对象的实例。这意味着它将自动处理像ChildClass这样的对象:
class ChildClass(object):
def __init__(self):
self.foo = 'foo'
self.bar = 1.1
self.parent = ParentClass(1)
这应该产生类似以下的JSON:
{ '__ChildClass__': {
'bar': 1.1,
'foo': 'foo',
'parent': {
'__ParentClass__': {
'foo': 1}
}
}
}