Skip to content

dizzy.generators.json_schema

dizzy.generators.json_schema

JSON Schema generator — compiles def/ LinkML sources into JSON Schema contracts.

Driven by the json_schema section of libconfig.yaml:

.. code-block:: yaml

json_schema:
  contracts: [commands, queries]   # commands | events | queries | models
  output_dir: gen_schema           # relative to the generate output directory

Omitting the section emits nothing, so a libconfig.yaml written before the section existed keeps producing byte-identical output. Present-but-empty (json_schema: {}) opts in with the defaults below.

One schema document is emitted per def/ source, mirroring the def/ layout — so every class in that source (each command, a query's Input and Output, …) is addressable as #/$defs/<ClassName>.

resolve_json_schema_settings(config)

Resolve (contracts, output_dir) from a LibConfig, or None if disabled.

Returns None when config is None or carries no json_schema section — the backwards-compatible default of emitting nothing.

Source code in dizzy/src/dizzy/generators/json_schema.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def resolve_json_schema_settings(config: LibConfig | None) -> tuple[list[str], str] | None:
    """Resolve ``(contracts, output_dir)`` from a LibConfig, or None if disabled.

    Returns None when *config* is None or carries no ``json_schema`` section — the
    backwards-compatible default of emitting nothing.
    """
    if config is None or config.json_schema is None:
        return None
    settings = config.json_schema
    contracts = (
        [str(c) for c in settings.contracts] if settings.contracts else list(DEFAULT_CONTRACTS)
    )
    unknown = [c for c in contracts if c not in CONTRACT_KINDS]
    if unknown:
        raise ValueError(
            f"unknown json_schema contract kind(s): {', '.join(sorted(unknown))} "
            f"(expected any of {', '.join(CONTRACT_KINDS)})"
        )
    return contracts, settings.output_dir or DEFAULT_JSON_SCHEMA_DIR

json_schema_sources(feat, output_dir, contracts)

Map the selected contract kinds to (def_source, relative_output) pairs.

Output paths are relative to the JSON Schema root and mirror def/.

Source code in dizzy/src/dizzy/generators/json_schema.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def json_schema_sources(
    feat: FeatureDefinition, output_dir: Path, contracts: list[str]
) -> list[tuple[Path, Path]]:
    """Map the selected contract kinds to ``(def_source, relative_output)`` pairs.

    Output paths are relative to the JSON Schema root and mirror ``def/``.
    """
    def_dir = output_dir / "def"
    pairs: list[tuple[Path, Path]] = []

    if "commands" in contracts and feat.commands:
        pairs.append((def_dir / "commands.yaml", Path("commands.schema.json")))
    if "events" in contracts and feat.events:
        pairs.append((def_dir / "events.yaml", Path("events.schema.json")))
    if "queries" in contracts:
        for query in feat.queries or []:
            pairs.append(
                (
                    def_dir / "queries" / f"{query.name}.yaml",
                    Path("queries") / f"{query.name}.schema.json",
                )
            )
    if "models" in contracts:
        for model in feat.models or []:
            pairs.append(
                (
                    def_dir / "models" / f"{model.name}.yaml",
                    Path("models") / f"{model.name}.schema.json",
                )
            )
    return pairs

write_json_schemas(feat, output_dir, config)

Emit JSON Schema for the contract kinds selected in libconfig.

Returns the list of written files (empty when the json_schema section is absent).

Source code in dizzy/src/dizzy/generators/json_schema.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def write_json_schemas(
    feat: FeatureDefinition, output_dir: Path, config: LibConfig | None
) -> list[Path]:
    """Emit JSON Schema for the contract kinds selected in libconfig.

    Returns the list of written files (empty when the ``json_schema`` section is absent).
    """
    resolved = resolve_json_schema_settings(config)
    if resolved is None:
        logger.debug("no json_schema section in libconfig — skipping JSON Schema generation")
        return []
    contracts, subdir = resolved

    root = gen_schema_root(output_dir, subdir)
    written: list[Path] = []
    for source, relative in json_schema_sources(feat, output_dir, contracts):
        if not source.exists():
            logger.warning("json_schema: %s not found — skipping", source)
            continue
        dest = root / relative
        run_linkml_json_schema(source, dest)
        written.append(dest)

    logger.debug(
        "generated JSON Schema",
        extra={"count": len(written), "contracts": contracts, "output_dir": str(root)},
    )
    return written