Python json encoding with classes that need custom encoders but which may themselves have nested data structures -


this simplified version of trying ... let's have

class x(object):     pass  x = x() y = x() x.val = {1:2,3:4} y.val = {1:2,3:x} 

how write custom json encoder recurses through encoding loop naturally ? not need json demonstrate class of type x, (a dot dict fine). actual example of may have data structures nested 10 deep.

obviously override default() method, not seem allow recursive calls - ie best have mess (and need json.loads otherwise thing gets double quoted / escaped):

class xencoder(json.jsonencoder):     def default(self, obj):         if isinstance(obj, x):             return json.loads(self.encode({x:getattr(obj,x) x in dir(obj) if "__" not in x}))         return json.jsonencoder.default(self, obj) 

maybe on kill used used mixin class follow:

def _default_json_encoder(obj):     """ default encoder, encountered must have to_dict method serialized.  """     if hasattr(obj, "to_dict"):         return obj.to_dict()     else:         raise typeerror('object of type %s value of %s not json serializable' % (type(obj), repr(obj)))  class mixinjsonable(object):     """     mixin pattern add capability object jsonable.      if object have to_dict method used produce dict, otherwise     mixinjsonable.to_dict used.      "public" attributes dump , instance of self._jsonable tuple.      attributes ignored passing ignored_keys parameter to_json method.     _ignored_json_keys (class attribute) update , spread on class using mixin.      """     # _ignored_json_keys = list()      def to_dict(self):         """         to_dict method dump public attributes.         """          self._jsonable = (int, list, str, dict)          _dict = dict()         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 none or hasattr(value, 'to_dict'):                 # to_dict method used serialization method.                 value = value             else:                 continue             _dict[attr] = value         return _dict      def to_json(self, **kw):         """         dump object json.          accept same keys :func json.dumps:. if ignored_keys (list) passed,         keys not dumped in json (filter on 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() 

will print:

{     "val": {         "1": 2,         "3": {             "val": {                 "1": 2,                 "3": 4             }         }     } } 

Comments

Popular posts from this blog

javascript - oscilloscope of speaker input stops rendering after a few seconds -

javascript - gulp-nodemon - nodejs restart after file change - Error: listen EADDRINUSE events.js:85 -

Fatal Python error: Py_Initialize: unable to load the file system codec. ImportError: No module named 'encodings' -