Example #1
0
def _do_load(json_obj: object, deserializer: callable, cls: type,
             initial: bool, **kwargs):
    try:
        result = deserializer(json_obj, cls, **kwargs)
        validate(result, cls, kwargs['fork_inst'])
    except Exception as err:
        clear()
        if isinstance(err, JsonsError):
            raise
        raise DeserializationError(str(err), json_obj, cls)
    else:
        if initial:
            # Clear all lru caches right before returning the initial call.
            clear()
        return result
Example #2
0
def _do_load(json_obj: object, deserializer: callable, cls: type,
             initial: bool, **kwargs):
    cls_name = get_class_name(cls, fully_qualified=True)
    if deserializer is None:
        raise DeserializationError(
            'No deserializer for type "{}"'.format(cls_name), json_obj, cls)
    try:
        result = deserializer(json_obj, cls, **kwargs)
        validate(result, cls, kwargs['fork_inst'])
    except Exception as err:
        clear()
        if isinstance(err, JsonsError):
            raise
        message = 'Could not deserialize value "{}" into "{}". {}'.format(
            json_obj, cls_name, err)
        raise DeserializationError(message, json_obj, cls)
    else:
        if initial:
            # Clear all lru caches right before returning the initial call.
            clear()
        return result
def load(json_obj: object,
         cls: Optional[Type[T]] = None,
         strict: bool = False,
         fork_inst: Optional[type] = StateHolder,
         attr_getters: Optional[Dict[str, Callable[[], object]]] = None,
         **kwargs) -> T:
    """
    Deserialize the given ``json_obj`` to an object of type ``cls``. If the
    contents of ``json_obj`` do not match the interface of ``cls``, a
    DeserializationError is raised.

    If ``json_obj`` contains a value that belongs to a custom class, there must
    be a type hint present for that value in ``cls`` to let this function know
    what type it should deserialize that value to.


    **Example**:

    >>> from typing import List
    >>> import jsons
    >>> class Person:
    ...     # No type hint required for name
    ...     def __init__(self, name):
    ...         self.name = name
    >>> class Family:
    ...     # Person is a custom class, use a type hint
    ...         def __init__(self, persons: List[Person]):
    ...             self.persons = persons
    >>> loaded = jsons.load({'persons': [{'name': 'John'}]}, Family)
    >>> loaded.persons[0].name
    'John'

    If no ``cls`` is given, a dict is simply returned, but contained values
    (e.g. serialized ``datetime`` values) are still deserialized.

    If `strict` mode is off and the type of `json_obj` exactly matches `cls`
    then `json_obj` is simply returned.

    :param json_obj: the dict that is to be deserialized.
    :param cls: a matching class of which an instance should be returned.
    :param strict: a bool to determine if the deserializer should be strict
    (i.e. fail on a partially deserialized `json_obj` or on `None`).
    :param fork_inst: if given, it uses this fork of ``JsonSerializable``.
    :param attr_getters: a ``dict`` that may hold callables that return values
    for certain attributes.
    :param kwargs: the keyword args are passed on to the deserializer function.
    :return: an instance of ``cls`` if given, a dict otherwise.
    """
    _check_for_none(json_obj, cls)
    if _should_skip(json_obj, cls, strict):
        validate(json_obj, cls, fork_inst)
        return json_obj
    if isinstance(cls, str):
        cls = get_cls_from_str(cls, json_obj, fork_inst)
    cls, meta_hints = _check_and_get_cls_and_meta_hints(
        json_obj, cls, fork_inst, kwargs.get('_inferred_cls', False))

    deserializer = get_deserializer(cls, fork_inst)

    # Is this the initial call or a nested?
    initial = kwargs.get('_initial', True)

    kwargs_ = {
        'strict': strict,
        'fork_inst': fork_inst,
        'attr_getters': attr_getters,
        'meta_hints': meta_hints,
        '_initial': False,
        **kwargs
    }
    try:
        result = deserializer(json_obj, cls, **kwargs_)
        validate(result, cls, fork_inst)
        if initial:
            # Clear all lru caches right before returning the initial call.
            clear()
        return result
    except Exception as err:
        clear()
        if isinstance(err, JsonsError):
            raise
        raise DeserializationError(str(err), json_obj, cls)