def METHOD_NAME(config, structure):
    def _validate_json_level(config, structure, path):
        missing = set(structure.keys()).difference(set(config.keys()))
        if missing:
            raise ValidationError("Keys {0} are missing".format(", ".join(["->".join(path + [m]) for m in missing])))
        extra = set(config.keys()).difference(set(structure.keys()))
        if extra:
            raise ValidationError("Keys {0} are not allowed".format(", ".join(["->".join(path + [m]) for m in extra])))
        # Keys are correct, validate datatypes
        for k, v in list(config.items()):
            fullkey = "->".join(path + [k])
            # Dicts don't have __name__
            if type(structure[k]) == dict:
                structtype = dict
            else:
                structtype = structure[k]
            structname = structtype.__name__
            valname = type(v).__name__
            if type(v) != structtype:
                raise ValidationError("Value for {0} should be of type {1}, not {2}".format(fullkey, structname, valname))
            if isinstance(v, dict):
                # Recursively check substructure
                _validate_json_level(v, structure[k], path + [k])
    _validate_json_level(config, structure, [])