Both json
and simplejson
support the extension of json.JSONEncoder
with the purpose of serializing non-base objects. From the documentation, however, I can't understand how to do this safely.
This is my encoder:
class ReprEncoder(json.JSONEncoder):
@staticmethod
def of(*types):
return ft.partial(ReprEncoder, types)
def __init__(self, repr_types, **kwargs):
self.__repr_types = repr_types
super(ReprEncoder, self).__init__(**kwargs)
def default(self, obj):
if type(obj) in self.__repr_types:
return 'r[%r]' % obj
return super(ReprEncoder, self).default(obj)
The of
methods allows me to provide the classes for which the serialization is supported, and I represent such objects with the convention r[%r]
. On deserialization, I plan to use a strategy like if it matches r[
... ]
, then deserialize with some (possibly safe!) eval
-like technique
With the assumption that, for some class C
, C.__repr__
works as expected I can call it as it follows:
c = C('foo', 'bar', 3)
json.dumps(c, cls=ReprEncoder.of(C))
From the documentation it's not clear how to escape strings which are accidentally matching my semantics. The idea would be: if the string to be encoded matches the r[
...]
syntax, then pre-pend a backslash + On deserialization, look behind r
for backslashes.
A trick like:
def default(self, obj):
# ...
if type(obj) in types.StringTypes and obj.startswith('r'):
obj = '\\' + obj
return super(ReprEncoder, self).default(obj)
Is not going to work, since the default
method is called only when the default encoder doesn't have a clue on how to decode data. Also the json.JSONEncode
is not implementing things like string
(or similar) whilch I could override.
Any hint?