YAML to Crystal
Paste YAML and instantly get matching Crystal struct definitions with inferred types and JSON::Serializable.
Example
Input YAML:
name: Ada
age: 36
address:
city: London
Output Crystal:
struct Address
include JSON::Serializable
property city : String
end
struct Root
include JSON::Serializable
property name : String
property age : Int32
property address : Address
end
How it works
The tool parses your YAML in the browser with js-yaml, walks the resulting value to infer a type model, then emits Crystal structs (one per nested object) using property declarations. Nested objects become their own structs and arrays are typed by their first element.
Good to know
YAML to Crystal turns a sample YAML document into ready-to-use Crystal struct definitions, inferring each field's type and wiring in the JSON::Serializable mixin so the result compiles and round-trips data immediately. It is aimed at Crystal developers who are consuming config files, API payloads, or fixtures and want a typed model without hand-writing every property line.
Reach for it when you have a concrete example of the data but no schema: paste the YAML, hit Convert, and you get one struct per nested object plus an alias Root or top-level Root struct as the entry point. Because it infers from values rather than a formal schema, the output is only as accurate as your sample, so feed it a representative document that exercises every field you care about.
To read the result, note how the inference maps real values: true/false become Bool, whole numbers become Int32, decimals become Float64, and anything else falls back to String. Nested mappings are extracted into their own structs (named from the key, with array keys singularized, e.g. projects yields a Project struct), and arrays are typed by their first non-null element. Keys that aren't valid Crystal identifiers are renamed and given an @[JSON::Field(key: "...")] annotation so the original name still parses.
A practical caveat: the tool only sees one example, so it cannot know which fields are optional or nullable. If a key is sometimes absent or sometimes null in production data, widen the generated type yourself (for instance String? instead of String) and double-check numeric fields that might overflow Int32, switching them to Int64 where needed. Everything runs locally in your browser, so you can paste sensitive config safely.
Frequently asked questions
How are types inferred from YAML?
Each scalar maps to a Crystal type: booleans to Bool, integers to Int32, decimals to Float64, and other values to String. Nested mappings become their own structs, and arrays are typed by their first non-null element, e.g. Array(String) or Array(Items).
Why does my struct use JSON::Serializable?
Crystal's JSON::Serializable mixin lets you parse and emit JSON (and the tool keys off the same shape your YAML describes) with Root.from_json(...). Keys that aren't valid Crystal identifiers get a @[JSON::Field(key: "...")] annotation so the original name is preserved.
Is my data uploaded anywhere?
No — this tool runs entirely in your browser. Your input never leaves your device and it works offline once loaded.
Is it free?
Yes, completely free with no sign-up and no limits.
People also ask
Does YAML to Crystal handle nested objects and arrays of objects?
Yes. Each nested mapping becomes its own struct named after its key, and arrays of objects are typed by their first non-null element, generating a singularized struct such as Project for a projects list.
What Crystal type does an empty array or empty object produce?
An empty array is typed as Array(JSON::Any) and an empty object becomes Hash(String, JSON::Any), since there is no sample value to infer a more specific type from.
Can I generate Crystal structs from JSON instead of YAML?
This page expects YAML input, but YAML is a superset of JSON, so valid JSON pasted into the input box parses correctly and produces the same struct output.
Why is my whole number turned into Int32 instead of Int64?
The tool maps finite integers to Int32 by default; if a value exceeds the Int32 range, edit the generated property to Int64 yourself, as the inference does not check magnitude.
How do I make a generated field optional or nullable in Crystal?
Add a question mark to the type, for example name : String?, which lets JSON::Serializable accept a missing or null value for that key. The tool cannot infer this from a single example.
What happens if my YAML key has spaces, dashes, or other invalid characters?
The key is converted into a valid Crystal property name and the original is preserved with a @[JSON::Field(key: "...")] annotation, so parsing still uses the source key name.
Do I need to install Crystal to use this converter?
No. The conversion runs entirely in your browser using js-yaml, so you only need a Crystal toolchain later if you want to compile or run the generated code.
Related tools