json loader objecthook

    :param load_module: Module that contains the various types
    :param pairs: key/value tuples (In our case, they are str/str)
    :return:

def loads_loader(load_module: types.ModuleType, pairs: Dict[str, str]) -> Optional[JSGValidateable]:
    """json loader objecthook

    :param load_module: Module that contains the various types
    :param pairs: key/value tuples (In our case, they are str/str)
    :return:
    """
    cntxt = load_module._CONTEXT

    # If the type element is a member of the JSON, load it
    possible_type = pairs[cntxt.TYPE] if cntxt.TYPE in pairs else None
    target_class = getattr(load_module, possible_type, None) if isinstance(possible_type, str) else None
    if target_class:
        return target_class(**pairs)

    # See whether there are any exception types that are valid for the incoming data
    for type_exception in cntxt.TYPE_EXCEPTIONS:
        if not hasattr(load_module, type_exception):
            raise ValueError(UNKNOWN_TYPE_EXCEPTION.format(type_exception))
        target_class = getattr(load_module, type_exception)
        target_strict = target_class._strict
        target_class._strict = False
        try:
            rval = target_class(**pairs)
        finally:
            target_class._strict = target_strict
        if is_valid(rval):
            return rval

    # If there is not a type variable and nothing fits, just load up the first (and perhaps only) exception
    # It will later fail any is_valid tests
    if not cntxt.TYPE and cntxt.TYPE_EXCEPTIONS:
        return getattr(load_module, cntxt.TYPE_EXCEPTIONS[0])(**pairs)

    if cntxt.TYPE in pairs:
        raise ValueError(f'Unknown reference type: "{cntxt.TYPE}": "{pairs[cntxt.TYPE]}"')
    else:
        raise ValueError(f'Missing "{cntxt.TYPE}" element')