def _get_flattener(self, obj): if util.is_primitive(obj): return lambda obj: obj list_recurse = self._list_recurse if util.is_list(obj): if self._mkref(obj): return list_recurse else: self._push() return self._getref # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.TUPLE: [self._flatten(v) for v in obj]} if util.is_set(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.SET: [self._flatten(v) for v in obj]} if util.is_dictionary(obj): return self._flatten_dict_obj if util.is_type(obj): return _mktyperef if util.is_object(obj): return self._ref_obj_instance if util.is_module_function(obj): return self._flatten_function # instance methods, lambdas, old style classes... self._pickle_warning(obj) return None
def _flatten_dict_obj(self, obj, data=None): """Recursively call flatten() and return json-friendly dict """ if data is None: data = obj.__class__() flatten = self._flatten_key_value_pair for k, v in sorted(obj.items(), key=util.itemgetter): flatten(k, v, data) # the collections.defaultdict protocol if hasattr(obj, 'default_factory') and callable(obj.default_factory): factory = obj.default_factory if util.is_type(factory): # Reference the type value = _mktyperef(factory) else: # Create an instance from the factory and assume that the # resulting instance is a suitable examplar. value = self._flatten(handlers.CloneFactory(factory())) data['default_factory'] = value return data