JSON1 / JSON to Go
JSON to Go
Generate Go structs with JSON tags from a JSON sample. Optional fields become pointers tagged omitempty, so encoding/json can tell absent from the zero value.
Processed locally·Your data never leaves your device
InputJSON
ReadyOutputGo
Converted output appears here as you type.
Good to know
- Every record in an array is inspected, not just the first, so a field that appears in only some of them is typed as optional rather than required.
- Identical nested shapes are emitted once and reused, and reserved words are renamed to something legal in this language.
About this tool
Every field in a Go struct needs a tag to map it to a JSON key, which makes hand-writing one for a large payload slow and easy to get subtly wrong. This produces the full set, with the field and tag columns aligned the way gofmt would align them, so it goes into a file without reformatting.
Exported names follow the conventions the linters actually enforce — an id key becomes ID, not Id, and url becomes URL — because a field must be exported for encoding/json to see it at all.
int64JSON integers. Explicitly sized rather than int, whose width depends on the platform.float64Fractional numbers. Also what encoding/json gives you for every number when decoding into an interface{}.*int64An optional field, tagged omitempty — a pointer is the only way to distinguish absent from zero.[]stringArrays. A nil slice and an empty one both marshal as [] with omitempty, and as null without it.interface{}A field with no observable type.
- Why are some fields pointers?
- Because
encoding/jsoncannot otherwise tell a field that was absent from one that arrived as the zero value. A missingcountand acountof 0 both leave anint64holding 0. The pointer plusomitemptyis the standard workaround, and it is the reason a generated Go struct looks noisier than the equivalent in a language with an option type. - Why interface{} instead of any?
anyis a type alias forinterface{}added in Go 1.18 — identical to the compiler, purely a spelling. The output uses the older form because it also compiles on earlier toolchains, and a struct definition is a bad place for a build to break over syntax.- Why is omitempty only on the pointer fields?
- Because on a value field it is a footgun:
omitemptyon a plainint64drops a real 0 from the encoded output, and on astringit drops a real empty string. It means "omit when this is the zero value", which is only the same as "omit when absent" if the field is a pointer. - Will large integers survive a round trip?
- In this struct, yes —
int64holds anything JSON can express as an integer. The failure case is decoding into aninterface{}or amap[string]interface{}, where every number becomesfloat64and integers above 2^53 lose precision silently. Using the generated struct is how you avoid that. - How are optional fields decided?
- Every record in an array is inspected, not just the first. A field that appears in some records and not others is typed as optional, and a value that is sometimes null widens accordingly. Generators that read only the first element get this wrong on exactly the payloads where it matters.
- What happens to a key that is a reserved word?
- It is renamed to something legal in the target language, and where the language supports it, an annotation records the original JSON key so serialisation still round-trips.
Related tools
- JSON to PythonGenerate Python dataclasses with type hints from a JSON sample. Optional fields default to None and are ordered after the required ones, so the class compiles as written.
- JSON to C#Generate C# classes with System.Text.Json attributes from a JSON sample. Properties are PascalCase with a JsonPropertyName holding the original key, and optional value types get a question mark.
- XML to JSONConvert XML to formatted JSON. Attributes become @name keys, repeated elements collapse into arrays, and mixed text lands under #text.