# odin-jsonschema Generates Odin type declarations from JSON Schema documents (draft-07 and 2020-12). The generated types parse with `core:encoding/json` — no runtime library required. ## Usage ### CLI ```sh make build # -> build/jschema build/jschema schema.json -o:types.odin # file to file cat schema.json | build/jschema # stdin to stdout build/jschema schema.json -pkg:api -root:Document ``` Flags: | flag | meaning | default | |------|---------|---------| | `-o:` | output file | stdout | | `-pkg:` | package name of the generated file | `schema` | | `-root:` | name of the root declaration | `Root` | Debug builds (`odin build src/cmd/jschema -debug`) wrap the allocator in `mem.Tracking_Allocator` and report leaks and bad frees on exit. ### Library ```odin import "src/pkg/jschema" err := jschema.generate("schema.json", "types.odin") ``` `generate_source` is the in-memory variant used for stdin/pipelines. All intermediate state lives in an internal arena that is freed before returning; the only caller-facing allocation is the returned source string. ## Type mapping | schema | Odin | |--------|------| | `string` / `integer` / `number` / `boolean` | `string` / `i64` / `f64` / `bool` | | `object` with `properties` (or `allOf`) | named `struct`, merged across `allOf` and `$ref` | | `object` with `additionalProperties` / single-pattern `patternProperties` | `map[string]T` | | `array` | `[]T` | | optional or nullable field | `Maybe(T)` | | `enum` of strings that are valid Odin identifiers | named `enum` (variant names match the JSON strings exactly, as required by `core:encoding/json`) | | `enum` otherwise | `string` | | `oneOf` / `anyOf` | `union {..}` (a `null` variant folds into `Maybe`/nil) | | `type: [..]` with several types | `union {..}` | | no usable constraints | `json.Value` | | `$ref` | named type; local pointers (`#/$defs/..`, `#/definitions/..`) and relative file refs are resolved | Recursive schemas work through slices and maps. A schema that contains itself *by value* (illegal in Odin, and `core:encoding/json` cannot unmarshal pointer fields) has the offending property emitted as `json.Value`. Known limitations: - `core:encoding/json` tries union variants in declaration order and skips unknown object keys, so for `oneOf` of similar objects the first variant that parses wins. - Tuple-form `items` / `prefixItems` degrade to `[]json.Value`. - `$anchor` and remote (URL) refs are not supported; unresolvable refs are an error. ## Internals The schema is stored data-oriented: one flat pool of fixed-size nodes plus shared side arrays (`props`, `children`, `names`, `strings`), all cross-linked by `u32` indices. Documents are lowered straight from the JSON tokenizer into the pool — no intermediate `json.Value` tree — which preserves declaration order and keeps output deterministic. ## Testing ```sh make test # unit + golden tests (odin test src/pkg/jschema) make e2e # generate -> compile -> parse sample.json per testdata case make bench # performance report (time, throughput, allocations, leaks) make check # test + e2e ``` Each directory under `testdata/cases/` holds a `schema.json`, the expected generated code (`expected.odin`), a `sample.json` instance, and a `check.odin` test that asserts the parsed values. The `openapi` case runs the full OpenAPI 3.2 document schema end-to-end.