json-schema-to-gdscript
v0.1.0
Published
Generate typed Godot 4 GDScript model classes from JSON Schema.
Maintainers
Readme
json-schema-to-gdscript
Generate typed Godot 4 RefCounted model classes from Draft 2020-12 JSON Schema.
The package provides both a Node.js API and the json-schema-to-gdscript CLI.
Capabilities
- Resolves local relative
$refdocuments and JSON Pointer fragments. - Generates deterministic, collision-safe
class_namedeclarations and file names. - Supports root objects, root arrays, named and inline objects, nested arrays, dictionaries, primitives, enums,
const, nullable types, andoneOf/anyOf. - Preserves snake_case JSON names and maps names that are not valid GDScript identifiers.
- Emits typed properties and typed arrays where GDScript can represent the schema safely.
- Emits schema metadata and runtime validation for constraints and unions. Unions that cannot be represented precisely are
Variantrather than an incorrect narrow type. - Generates
from_dict()/to_dict()for object models andfrom_array()/to_array()for root arrays. - Converts nested dictionaries and arrays to generated model instances and back.
- Rejects unknown properties when
additionalPropertiesisfalse; otherwise preserves them and validates a declaredadditionalPropertiesschema. - Carries schema descriptions into generated Godot documentation comments.
Installation
npm install json-schema-to-gdscriptNode.js 20 or newer is required.
CLI
Pass the root schema and destination directory:
npx json-schema-to-gdscript ./schema/root.schema.json ./godot/generatedDragon Warrior example:
npm run build
node dist/cli.js \
examples/dragon-warrior/schemas/v1/dragon_warrior_v1.schema.json \
/tmp/dragon-warrior-gdscriptThe root schema's complete local reference graph is loaded. One .gd file is
written for each generated model, plus generated_json_schema_runtime.gd.
Programmatic API
import { generate } from "json-schema-to-gdscript";
const result = await generate({
schemaPath: "./schema/root.schema.json",
outputDirectory: "./godot/generated"
});
console.log(result.rootClassName);
console.log(result.files.map((file) => file.path));The package also exports naming helpers, SchemaRepository, and its public
TypeScript types.
Generated code
Given a required nested object and an optional union, generated code follows this shape:
class_name Player
extends RefCounted
var profile: PlayerProfile
var selected_item: Variant
static func from_dict(data: Variant) -> Player:
# Required properties and schema constraints are validated before assignment.
# Nested dictionaries become generated model instances.
pass
func to_dict() -> Dictionary:
# Nested models are serialized and optional-property presence is preserved.
return {}Actual generated files include complete implementations, constraint metadata,
explicit push_error() failures, enum value constants, and unknown-property
handling.
Limitations
- References must resolve to local files. HTTP(S) schema fetching is intentionally not performed.
- GDScript cannot express arbitrary JSON Schema unions as static types. These
values are generated as
VariantwithVALUE_SCHEMAorPROPERTY_SCHEMASmetadata and runtime validation. - String enums remain typed
Stringvalues because GDScript enums are integer based. Allowed strings are emitted as*_VALUESconstants. - This release covers the validation keywords used by the included Dragon
Warrior fixture: types, required properties, enums, constants, numeric and
length bounds, item bounds, patterns, unions, and
additionalProperties. Other Draft 2020-12 applicator and annotation keywords remain available in the source schema but are not yet enforced by generated runtime validation. - Remote references, recursive schema graphs, dynamic references, and custom vocabularies are not currently supported.
Development
npm install
npm run build
npm testThe integration test generates the full schema graph under
examples/dragon-warrior/schemas/v1/ and validates every emitted script with:
/snap/bin/godot4 --headless --editor --quit --path <temporary-project>It then preloads all scripts in a headless Godot run so parser failures cannot be hidden by unreferenced output.
Release
- Update the version in
package.json. - Run
npm test,npm run build, andnpm pack --dry-run. - Inspect the tarball contents and confirm
npm view json-schema-to-gdscriptstill reports the intended package/version as available. - Push the matching
v<version>tag. The release workflow tests with Godot, packs the npm tarball, uploads it as a workflow artifact, and attaches it to the GitHub Release. - Publish to npm separately with
npm publish --access publicwhen desired.
prepublishOnly reruns the test suite and build before publication.
