def auto_converter(tt): '''Auto convert attempt a number of ways of finding appropriate converters to a unhandled type. The first strategy is to check if the type is supported in the mod:`pyson.jsonfy_extras` module. If that is not the case, it searches for converters for the superclasses of `tt`. Finally, if that fails an error is raised. ''' # Tries to import a converter from jsonfy_ext.* modules name = type2name(tt) try: load_modules('pyson.jsonfy_extras.ext_' + name) except AttributeError: pass try: return CONVERTERS[tt] except KeyError: pass # Tries to use a converter for a base class (hint: this often fails!) for base_t in tt.mro()[:-1]: try: return CONVERTERS[base_t] except KeyError: pass else: raise TypeError('object of type %s is not supported' % tt) def not_supported(obj): raise TypeError('object of type %s is not supported' % tt) return not_supported
def jsonfy(obj, json_level=None, print_type=True, invertible=False, recursive=True): '''Return a JSON representation of object. Parameters ---------- obj : anything Object to be converted to JSON json_level : int Maximum JSON level allowed for the given type. print_type : bool Set to False to prevent adding the ('@type': value) pair to the resulting object. This key is used to convert the JSON object to the appropriate Python type. invertible : bool If True, the output can be converted back to an identical Python object. The default behavior is to allow approximate types, e.g., ``str`` can be converted to ``unicode``, ``tuple`` to ``list`` and so on. recursive : bool If False and json_level is respected or not set, it prevents recursive application of func:`jsonfy` to child nodes of the JSON result. ''' tt = type(obj) if json_level is not None or invertible: raise NotImplementedError # Compute the result from the converter function try: function = CONVERTERS[tt] except KeyError: function = auto_converter(tt) try: result = function(obj) except Exception as ex: msg = 'unhandled exception raised when jsonfy-ing %s object\n %s: %s' msg = msg % (type(obj), type(ex).__name__, ex) raise RuntimeError(msg) # Print type if print_type and not is_object_t(tt): try: result[u'@type'] = type2name(tt) except: pass #TODO: move recursive to converter function if recursive: if isinstance(result, dict): for k, v in result.items(): result[k] = jsonfy(v, json_level=json_level, print_type=print_type, invertible=invertible, recursive=recursive) elif isinstance(result, list): for idx, v in enumerate(result): result[idx] = jsonfy(v, json_level=json_level, print_type=print_type, invertible=invertible, recursive=recursive) return result
def unjsonfy(json, tt=None, recursive=True, inplace=False, lazy=True): """Create object from its JSON representation Parameters ---------- json : JSON-like JSON-like structure to be converted to a Python object. tt (optional): type Type of the output object (can be inferred from the '@type' key, if ``json`` has it. recursive : bool If False, prevents recursive application of func:`jsonfy` to child nodes of the JSON input. """ if tt is None: try: tt = json[u"@type"] except: if not lazy: raise ValueError("'tt' must be set explicity if 'json' does not have a '@type' key") else: tt = None else: tt = name2type(tt) # TODO: move 'inplace' and 'recursive' to the converter function if not inplace: json = deepcopy(json) if recursive: if isinstance(json, dict): for k, v in json.items(): json[k] = unjsonfy(v, recursive=True, inplace=True) elif isinstance(json, list): for idx, v in enumerate(json): json[idx] = unjsonfy(v, recursive=True, inplace=True) # Compute the result from the converter function try: converter = CONVERTERS[tt] except KeyError: # Tries to load converters from unjsonfy_extras try: load_modules("pyson.unjsonfy_extras.ext_" + type2name(tt)) except AttributeError: pass try: converter = CONVERTERS[tt] except KeyError: if tt is None: return json raise ValueError("there is no known converter to type %s" % tt) return converter(json)
def unjsonfy(json, tt=None, recursive=True, inplace=False, lazy=True): '''Create object from its JSON representation Parameters ---------- json : JSON-like JSON-like structure to be converted to a Python object. tt (optional): type Type of the output object (can be inferred from the '@type' key, if ``json`` has it. recursive : bool If False, prevents recursive application of func:`jsonfy` to child nodes of the JSON input. ''' if tt is None: try: tt = json[u'@type'] except: if not lazy: raise ValueError("'tt' must be set explicity if 'json' does not have a '@type' key") else: tt = None else: tt = name2type(tt) #TODO: move 'inplace' and 'recursive' to the converter function if not inplace: json = deepcopy(json) if recursive: if isinstance(json, dict): for k, v in json.items(): json[k] = unjsonfy(v, recursive=True, inplace=True) elif isinstance(json, list): for idx, v in enumerate(json): json[idx] = unjsonfy(v, recursive=True, inplace=True) # Compute the result from the converter function try: converter = CONVERTERS[tt] except KeyError: # Tries to load converters from unjsonfy_extras try: load_modules('pyson.unjsonfy_extras.ext_' + type2name(tt)) except AttributeError: pass try: converter = CONVERTERS[tt] except KeyError: if tt is None: return json raise ValueError('there is no known converter to type %s' % tt) return converter(json)