kiln_ai.datamodel.json_schema

 1import json
 2from typing import Annotated, Dict
 3
 4import jsonschema
 5import jsonschema.exceptions
 6import jsonschema.validators
 7from pydantic import AfterValidator
 8
 9JsonObjectSchema = Annotated[
10    str,
11    AfterValidator(lambda v: _check_json_schema(v)),
12]
13
14
15def _check_json_schema(v: str) -> str:
16    # parsing returns needed errors
17    schema_from_json_str(v)
18    return v
19
20
21def validate_schema(instance: Dict, schema_str: str) -> None:
22    schema = schema_from_json_str(schema_str)
23    v = jsonschema.Draft202012Validator(schema)
24    return v.validate(instance)
25
26
27def schema_from_json_str(v: str) -> Dict:
28    try:
29        parsed = json.loads(v)
30        jsonschema.Draft202012Validator.check_schema(parsed)
31        if not isinstance(parsed, dict):
32            raise ValueError(f"JSON schema must be a dict, not {type(parsed)}")
33        if (
34            "type" not in parsed
35            or parsed["type"] != "object"
36            or "properties" not in parsed
37        ):
38            raise ValueError(f"JSON schema must be an object with properties: {v}")
39        return parsed
40    except jsonschema.exceptions.SchemaError as e:
41        raise ValueError(f"Invalid JSON schema: {v} \n{e}")
42    except json.JSONDecodeError as e:
43        raise ValueError(f"Invalid JSON: {v}\n {e}")
44    except Exception as e:
45        raise ValueError(f"Unexpected error parsing JSON schema: {v}\n {e}")
JsonObjectSchema = typing.Annotated[str, AfterValidator(func=<function <lambda>>)]
def validate_schema(instance: Dict, schema_str: str) -> None:
22def validate_schema(instance: Dict, schema_str: str) -> None:
23    schema = schema_from_json_str(schema_str)
24    v = jsonschema.Draft202012Validator(schema)
25    return v.validate(instance)
def schema_from_json_str(v: str) -> Dict:
28def schema_from_json_str(v: str) -> Dict:
29    try:
30        parsed = json.loads(v)
31        jsonschema.Draft202012Validator.check_schema(parsed)
32        if not isinstance(parsed, dict):
33            raise ValueError(f"JSON schema must be a dict, not {type(parsed)}")
34        if (
35            "type" not in parsed
36            or parsed["type"] != "object"
37            or "properties" not in parsed
38        ):
39            raise ValueError(f"JSON schema must be an object with properties: {v}")
40        return parsed
41    except jsonschema.exceptions.SchemaError as e:
42        raise ValueError(f"Invalid JSON schema: {v} \n{e}")
43    except json.JSONDecodeError as e:
44        raise ValueError(f"Invalid JSON: {v}\n {e}")
45    except Exception as e:
46        raise ValueError(f"Unexpected error parsing JSON schema: {v}\n {e}")