Generate Go structs with yaml.v3 tags from a YAML document — nested mappings as their own types, sometimes-absent keys marked omitempty, stringified non-string keys and interface{} slots all reported. Your input is never auto-saved: YAML is configuration, and configuration carries secrets. Free, no sign-up — runs locally in your browser.
Why generate Go structs from a YAML sample?
Half the YAML in the world is configuration for Go programs —
Helm values, CI pipelines, application config — and the other
half is data those programs consume. Either way, somebody
writes the struct by hand, key by key, and the failure mode is
silence: yaml.v3 does not complain about a key your struct
forgot; it just leaves the field zero and your program runs on
a wrong value. Generating the struct from a real sample inverts
that risk. Every key in the sample gets a field with the right
yaml: tag, nested mappings become their own types,
sequences of mappings merge into one element type — and the
judgement calls (a key that only sometimes appears, a value
that is null) are written into the notes instead of being
buried in the output.
How to use this tool
- Paste the YAML, upload a file, or drop one on the panel. One document only — multi-document files are refused with an explanation.
- Name the root type.
Config is the default because that is what most YAML pasted here turns out to be. - Press Generate Go structs. The root type comes first.
- Read the notes if any appear:
interface typings, stringified keys and anchor effects are all listed there. - Copy or download, and remember the input was never saved — if you clear the box, the YAML is gone from this tool entirely.
The mapping rules
Mappings become structs, with the tag carrying
the key verbatim; a key missing from some items of a sequence
also gains ,omitempty. Sequences
become slices, and a sequence of mappings yields one merged
element struct. Scalars infer like JSON:
whole numbers int64, decimals float64,
true/false bool, everything else
string — including dates, which this parser hands
over as strings, so a when: 2024-01-15 field is a
string unless you swap in time.Time yourself.
Nulls and mixed slots become
interface and are always noted. Identical shapes
share one struct.
Worked example
Given this service configuration (the second endpoint has no retries):
service: api
replicas: 3
endpoints:
- path: /health
retries: 0
- path: /metrics
the converter emits:
type Config struct {
Service string `yaml:"service"`
Replicas int64 `yaml:"replicas"`
Endpoints []Endpoint `yaml:"endpoints"`
}
type Endpoint struct {
Path string `yaml:"path"`
Retries int64 `yaml:"retries,omitempty"`
}
The omitempty on Retries is the
second endpoint talking: the sample proves the key comes and
goes, so marshalling should be allowed to leave it out too.
Frequently asked questions
Why the gopkg.in/yaml.v3 package and not encoding something?
Go's standard library has no YAML package — encoding/yaml does not exist — so every Go program reads YAML through a library, and gopkg.in/yaml.v3 is the de-facto standard one. The generated tags are yaml.v3 tags; other libraries (such as the Kubernetes sigs.k8s.io/yaml, which converts through JSON) read the same key names but do not honour omitempty identically, so if you use one of those, treat the tags as key names and check the option behaviour in that library's docs.
What does omitempty do on these structs?
It appears on fields whose key is missing from some items of a sequence in your sample. On the way out (marshalling), an empty value with omitempty is left out of the document instead of being written as a zero — which is exactly the behaviour the sample demonstrates. On the way in it changes nothing: a missing key still decodes to the zero value, and YAML gives you no way to distinguish absent from present-but-zero without pointers, which is why the XML generator on this site reaches for *T and this one does not — YAML mappings rarely need the distinction, and the omitempty in the output marks exactly the fields where absence was observed.
My YAML has several documents separated by ---. What happens?
The converter refuses, and says how many documents it found. Each document would need its own root type, and quietly generating the first (or merging them) would produce structs that misdescribe your file. Split the documents and convert each one, or rename the root per document — that is a modelling decision, so the tool leaves it to you.
I use anchors and aliases. Do they survive?
They are resolved before generation: an aliased mapping is seen as the full mapping it points at, so the generated struct describes the values, not the anchor syntax. If two keys alias mappings with the same shape, they share one struct type, like any identical shapes. What is lost is the sharing itself — the struct cannot say 'these two fields are the same object'. If your program depends on that identity rather than the values, no struct generator can express it.
My keys aren't strings — YAML allows that. What happens to them?
Go struct tags must be strings, so a numeric or boolean YAML key is stringified in the tag (42 becomes "42") and the notes call out every key it happens to. Be aware that this is a lossy step in one direction: yaml.v3 will decode the document key '42' into the string key "42" for a struct field, which matches, but if your program reads the file into a map as well, the map key keeps its original type and the two views differ.
Why int64 here when the XML converter uses int?
Because the JSON-family generators this converter shares its core with use int64, and YAML documents in Go programs are overwhelmingly configuration and data files where the extra width costs nothing. If you are generating for a memory-tight embedded target, narrowing the widths afterwards is a one-line-per-field edit; the sample cannot know your target, so it picks the width that cannot overflow on ordinary data.