可能是过度杀戮,但我曾经用过一个Mixin类,如下所示:def _default_json_encoder(obj):
""" Default encoder, encountered must have to_dict method to be serialized. """
if hasattr(obj, "to_dict"):
return obj.to_dict()
else:
raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj)))
class MixinJSONable(object):
"""
Mixin pattern to add a capability to an object to be jsonable.
If object have to_dict method it will be used to produce the dict, otherwise
MixinJSONable.to_dict will be used.
Only "public" attributes will be dump and instance of self._jsonable tuple.
Attributes could be ignored by passing ignored_keys parameter to to_json method.
Thus _ignored_json_keys (class attribute) will be update and spread over all class using this Mixin.
"""
# _ignored_json_keys = list()
def to_dict(self):
"""
to_dict method to dump public attributes.
"""
self._jsonable = (int, list, str, dict)
_dict = dict()
for attr in dir(self):
value = getattr(self, attr)
if attr.startswith("_") or attr in getattr(MixinJSONable, "_ignored_json_keys", []):
continue
elif isinstance(value, self._jsonable) or value is None or hasattr(value, 'to_dict'):
# to_dict method is used as serialization method.
value = value
else:
continue
_dict[attr] = value
return _dict
def to_json(self, **kw):
"""
Dump object as Json.
Accept the same keys than :func json.dumps:. If ignored_keys (list) is passed,
the keys will not be dumped in the json (filter over all sons)
"""
indent = kw.pop("indent", 4) # use indent key if passed otherwise 4.
_ignored_json_keys = kw.pop("ignored_keys", [])
if _ignored_json_keys:
MixinJSONable._ignored_json_keys = _ignored_json_keys
return json.dumps(self, indent=indent, default=_default_json_encoder, **kw)
class X(MixinJSONable):
pass
x = X()
y = X()
setattr(x,"val",{1:2,3:4})
setattr(y,"val",{1:2,3:x})
y.to_json()
将打印:
^{pr2}$