SchemaLint

JSON Schema linter for static type compatibility.
Overview
schemalint validates JSON Schema files for compatibility with statically-typed languages like Go, Rust, TypeScript, and others. It catches patterns that cause problems in code generation before they become runtime issues.
Installation
Homebrew
brew install grokify/tap/schemalint
Go Install
go install github.com/grokify/schemalint/cmd/schemalint@latest
Usage
Generate Schema from Go Types
Generate a JSON Schema from Go struct types:
schemalint generate github.com/myorg/myproject/types Config
schemalint generate -o schema.json github.com/myorg/myproject/types Config
This creates a temporary Go program that uses invopop/jsonschema to reflect on your type and generate the schema. The target package can be local (in GOPATH/src) or remote.
Lint Schema
Check a JSON Schema for patterns that cause problems in code generation:
schemalint lint schema.json
Profiles
Use --profile to select a linting profile:
schemalint lint schema.json # default profile
schemalint lint schema.json --profile scale # strict scale profile
| Profile |
Description |
default |
Standard checks for discriminators, union size, nesting |
scale |
Strict mode that disallows composition keywords for clean static types |
schemalint lint --output text schema.json # Human-readable (default)
schemalint lint --output json schema.json # Machine-readable JSON
schemalint lint --output github schema.json # GitHub Actions annotations
Exit Codes
| Code |
Meaning |
| 0 |
No issues found |
| 1 |
Errors found (schema has problems) |
| 2 |
Warnings found but no errors |
Lint Checks
Default Profile
Errors
| Code |
Description |
union-no-discriminator |
Union (anyOf/oneOf) has no discriminator field |
inconsistent-discriminator |
Variants use different discriminator field names |
missing-const |
Union variant lacks const value for discriminator |
duplicate-const-value |
Multiple variants have the same discriminator value |
invalid-property-case |
Property name does not follow the configured case convention |
Warnings
| Code |
Description |
large-union |
Union has more than 10 variants |
nested-union |
Union nested more than 2 levels deep |
additional-properties |
Union variant has additionalProperties: true |
Scale Profile
The scale profile includes all default checks plus these additional errors:
| Code |
Description |
composition-disallowed |
Disallow anyOf, oneOf, allOf |
additional-properties-disallowed |
Disallow additionalProperties: true |
missing-type |
Require explicit type field |
mixed-type-disallowed |
Disallow type arrays like ["string", "number"] |
Example
Given this schema with a union that lacks a discriminator:
{
"$defs": {
"Response": {
"anyOf": [
{"type": "object", "properties": {"data": {"type": "string"}}},
{"type": "object", "properties": {"error": {"type": "string"}}}
]
}
}
}
Running schemalint lint will report:
[error] $/$defs/Response/anyOf: anyOf union has no discriminator field
suggestion: Add a const property (e.g., 'type' or 'kind') to each variant with a unique value
Summary: 1 error(s), 0 warning(s)
Fix by adding a discriminator:
{
"$defs": {
"Response": {
"anyOf": [
{
"type": "object",
"properties": {
"type": {"const": "success"},
"data": {"type": "string"}
}
},
{
"type": "object",
"properties": {
"type": {"const": "error"},
"error": {"type": "string"}
}
}
]
}
}
}
Roadmap
See TASKS.md for planned features including:
- Code generation for Go, Rust, TypeScript
- Full
$ref resolution
- OpenAPI 3.1 support
References
License
MIT License - see LICENSE for details.