github.com/spider-gazelle/json-schema
1.3.3 / published Jun 14, 2026 / repository
Describe crystal-lang JSON serializable types with JSON Schema
JSON Schema 
A crystal lang tool for converting JSON serialisable class definitions into the JSON Schema representation.
Installation
dependencies:
json-schema:
github: spider-gazelle/json-schema
Usage
basic type support
require "json-schema"
String.json_schema #=> {type: "string"}
Int32.json_schema #=> {type: "integer", format: "Int32"}
Float32.json_schema #=> {type: "number", format: "Float32"}
Array(String | Int32).json_schema #=> { type: "array", items: { anyOf: [{type: "integer", format: "Int32"}, {type: "string"}] } }
# Works with enums
enum TestEnum
Option1
Option2
end
TestEnum.json_schema #=> {type: "string", enum: ["option1", "option2"]}
json serialisable support is included too, with deeply nested objects etc.
require "json-schema"
class MyType
include JSON::Serializable
getter string : String
getter symbol : Symbol?
getter time : Time
getter integer : Int32
getter union_type : String | Int64 | Bool
end
MyType.json_schema
# outputs
{
type: "object",
properties: {
string: {type: "string"},
symbol: {type: "string"},
time: {type: "string", format: "date-time"},
integer: {type: "integer", format: "Int32"},
union_type: {anyOf: [{type: "boolean"}, {type: "integer", format: "Int64"}, {type: "string"}]}
},
required: ["string", "time", "integer", "union_type"]
}
You can also customize schema output using the @[JSON::Field] annotation
require "json-schema"
class MyType
include JSON::Serializable
# The `EpochConverter` here means the JSON value will actually be an integer
# so to avoid the output being `type: "string", format: "date-time"` you can
# supply a type override and custom format string.
@[JSON::Field(converter: Time::EpochConverter, type: "integer", format: "Int64")]
getter time : Time
# or if you just want to provide a custom format
@[JSON::Field(format: "email")]
getter email : String
end
for anything too confusing it falls back to a generic { type: "object" } however this should only happen in some cases where you've inherited generic objects. e.g. class Me < Hash(String, Int32) (although this case is handled correctly)
API
- Array(T)
An
Arrayis an ordered, integer-indexed collection of objects of type T. - Bool
Bool has only two possible values:
trueandfalse. - Enum
Enum is the base type of all enums.
- Float
Float is the base type of all floating point numbers.
- Hash(K, V)
A
Hashrepresents a collection of key-value mappings, similar to a dictionary. - Int
Int is the base type of all integer types.
- JSON
The JSON module allows parsing and generating JSON documents.
- NamedTuple(**T)
A named tuple is a fixed-size, immutable, stack-allocated mapping of a fixed set of keys to values.
- Nil
The
Niltype has only one possible value:nil. - Set(T)
Setimplements a collection of values with no duplicates. - String
A
Stringrepresents an immutable sequence of UTF-8 characters. - Symbol
A symbol is a constant that is identified by a name without you having to give it a numeric value.
- Time
Timerepresents a date-time instant in incremental time observed in a specific time zone. - Tuple(*T)
A tuple is a fixed-size, immutable, stack-allocated sequence of values of possibly different types.
- UUID
Represents a UUID (Universally Unique IDentifier).