def _flatten_obj_instance(self, obj): """Recursively flatten an instance and return a json-friendly dict """ data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') has_slots = not has_dict and hasattr(obj, '__slots__') has_getstate = has_dict and hasattr(obj, '__getstate__') has_getstate_support = has_getstate and hasattr(obj, '__setstate__') HandlerClass = handlers.registry.get(type(obj)) if (has_class and not util.is_repr(obj) and not util.is_module(obj)): module, name = _getclassdetail(obj) if self.unpicklable is True: data[tags.OBJECT] = '%s.%s' % (module, name) # Check for a custom handler if HandlerClass: handler = HandlerClass(self) return handler.flatten(obj, data) if util.is_module(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__name__, obj.__name__) else: data = unicode(obj) return data if util.is_repr(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__class__.__module__, repr(obj)) else: data = unicode(obj) return data if util.is_dictionary_subclass(obj): return self._flatten_dict_obj(obj, data) if util.is_noncomplex(obj): return [self.flatten(v) for v in obj] if has_dict: # Support objects that subclasses list and set if util.is_collection_subclass(obj): return self._flatten_collection_obj(obj, data) # Support objects with __getstate__(); this ensures that # both __setstate__() and __getstate__() are implemented if has_getstate_support: data[tags.STATE] = self.flatten(obj.__getstate__()) return data # hack for zope persistent objects; this unghostifies the object getattr(obj, '_', None) return self._flatten_dict_obj(obj.__dict__, data) if has_slots: return self._flatten_newstyle_with_slots(obj, data)
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): return self._pop([self.flatten(v) for v in obj]) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): return self._pop({tags.TUPLE: [self.flatten(v) for v in obj]}) if util.is_set(obj): return self._pop({tags.SET: [self.flatten(v) for v in obj]}) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') if self._mkref(obj): if has_class and not util.is_repr(obj): module, name = _getclassdetail(obj) if self.unpicklable is True: data[tags.OBJECT] = '%s.%s' % (module, name) if util.is_repr(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__class__.__module__, repr(obj)) else: data = unicode(obj) return self._pop(data) if util.is_dictionary_subclass(obj): return self._pop(self._flatten_dict_obj(obj, data)) if util.is_noncomplex(obj): return self._pop([self.flatten(v) for v in obj]) if has_dict: return self._pop(self._flatten_dict_obj( obj.__dict__, data)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) return self._pop(data)
def flatten(self, obj): """Takes an object and returns a JSON-safe representation of it. Simply returns any of the basic builtin datatypes >>> p = Pickler() >>> p.flatten('hello world') 'hello world' >>> p.flatten(u'hello world') u'hello world' >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) {'key': 'value'} """ self._push() if self._depth == self._max_depth: return self._pop(repr(obj)) if util.is_primitive(obj): return self._pop(obj) if util.is_list(obj): return self._pop([ self.flatten(v) for v in obj ]) # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): return self._pop({tags.TUPLE: [ self.flatten(v) for v in obj ]}) if util.is_set(obj): return self._pop({tags.SET: [ self.flatten(v) for v in obj ]}) if util.is_dictionary(obj): return self._pop(self._flatten_dict_obj(obj, obj.__class__())) if util.is_type(obj): return self._pop(_mktyperef(obj)) if util.is_object(obj): data = {} has_class = hasattr(obj, '__class__') has_dict = hasattr(obj, '__dict__') if self._mkref(obj): if has_class and not util.is_repr(obj): module, name = _getclassdetail(obj) if self.unpicklable is True: data[tags.OBJECT] = '%s.%s' % (module, name) if util.is_repr(obj): if self.unpicklable is True: data[tags.REPR] = '%s/%s' % (obj.__class__.__module__, repr(obj)) else: data = unicode(obj) return self._pop(data) if util.is_dictionary_subclass(obj): return self._pop(self._flatten_dict_obj(obj, data)) if util.is_noncomplex(obj): return self._pop([self.flatten(v) for v in obj]) if has_dict: return self._pop(self._flatten_dict_obj(obj.__dict__, data)) else: # We've seen this object before so place an object # reference tag in the data. This avoids infinite recursion # when processing cyclical objects. return self._pop(self._getref(obj)) return self._pop(data)