def from_json(record_type, json_struct): """JSON marshall in function: a 'visitor' function which looks for JSON types/hints on types being converted to, but does not require them. Args: ``record_type=``\ *TYPE* Record type to convert data to ``json_struct=``\ *DICT|LIST* a loaded (via ``json.loads``) data structure, normally a dict or a list. """ if issubclass(record_type, JsonRecord): return record_type(json_struct) elif issubclass(record_type, Record): # do what the default JsonRecord __init__ does init_kwargs = json_to_initkwargs(record_type, json_struct) instance = record_type(**init_kwargs) return instance else: raise exc.JsonRecordCoerceError( given=repr(json_struct), type=record_type.__name__, )
def json_to_initkwargs(record_type, json_struct, kwargs=None): """This function converts a JSON dict (json_struct) to a set of init keyword arguments for the passed Record (or JsonRecord). It is called by the JsonRecord constructor. This function takes a JSON data structure and returns a keyword argument list to be passed to the class constructor. Any keys in the input dictionary which are not known are passed as a single ``unknown_json_keys`` value as a dict. This function should generally not be called directly, except as a part of a ``__init__`` or specialized visitor application. """ if kwargs is None: kwargs = {} if json_struct is None: json_struct = {} if not isinstance(json_struct, dict): raise exc.JsonRecordCoerceError( passed=json_struct, recordtype=record_type, ) unknown_keys = set(json_struct.keys()) for propname, prop in record_type.properties.items(): # think "does" here rather than "is"; the slot does JSON if isinstance(prop, JsonProperty): json_name = prop.json_name if json_name is not None: if json_name in json_struct: if propname not in kwargs: try: kwargs[propname] = _json_to_value_initializer( prop.from_json( json_struct[json_name] ), prop.valuetype, ) except Exception as e: raise _box_ingress_error(json_name, e) unknown_keys.remove(json_name) elif prop.name in json_struct: json_val = json_struct[prop.name] unknown_keys.remove(prop.name) if prop.name not in kwargs: proptype = prop.valuetype try: kwargs[propname] = _json_to_value_initializer( json_val, proptype, ) except Exception as e: raise _box_ingress_error(prop.name, e) if unknown_keys: kwargs["unknown_json_keys"] = dict( (k, deepcopy(json_struct[k])) for k in unknown_keys ) return kwargs