Overview
Introduction
Writing Go structs by hand for a JSON payload means getting several small but easy-to-miss details right: exported PascalCase field names, a `json:"..."` tag preserving every original key, and remembering that `encoding/json` decodes every JSON number as `float64` by default. This tool infers all of that directly from a real JSON sample.
It's one of four sibling generators on this site (TypeScript, Python, Go, Zod) that share the same shape-inference logic and differ only in how that shape is rendered as target-language code.
What Is JSON to Go Struct?
A generator that infers Go types from a JSON sample and emits `struct` type declarations: `string`/`float64`/`bool` for primitives, `[]T` for arrays, and a separate named struct type for every nested object, each field carrying a `json:"originalKey"` tag that preserves the exact JSON key regardless of how the Go field name itself was PascalCased.
Fields observed as `null`, or missing from some elements of a merged array of objects, become pointer types (`*T`) with `,omitempty` added to their struct tag, since Go has no other way to distinguish an absent/null value from that type's ordinary zero value.
The output is plain Go source text, ready to paste into a `.go` file and use directly with `encoding/json`'s `Marshal`/`Unmarshal`.
How JSON to Go Struct Works
The generator parses your JSON, then walks it via the same shared shape-inference step used by this site's TypeScript, Python, and Zod generators, classifying every value (string, integer, float, boolean, null, an array, or an object with named fields, tracking per-field nullability and, for arrays of objects, optionality).
Rendering that shape as Go hoists every object shape into its own named `struct` type declaration (reserving a unique name, appending a numeric suffix on a naming collision), with every JSON number, integer or float alike, rendered as `float64` to match `encoding/json`'s actual default decoding behavior rather than a type this tool merely guesses would be nicer.
Every field gets a `json:"key"` tag with the exact original JSON key (adding `,omitempty` for nullable/optional fields), and field names and types within a struct are padded to roughly align in columns, similar to `gofmt`'s output.
When To Use JSON to Go Struct
Use it right after capturing a real API response or config sample, when you want Go structs ready to `Unmarshal` that payload without hand-transcribing every field, its Go-idiomatic name, and its struct tag.
It's also a fast way to avoid a common Go gotcha: forgetting that `encoding/json` decodes numbers as `float64` by default, which this tool bakes in from the start instead of leaving you to discover it the first time a decode produces an unexpected type.
Often used alongside JSON to TypeScript Interface, JSON to Python Dataclass and JSON to Zod Schema.
Features
Advantages
- Matches `encoding/json`'s real default numeric decoding behavior (float64 for every JSON number) instead of guessing int vs. float, avoiding a common runtime type mismatch.
- Adds a correct `json:"..."` tag preserving the exact original JSON key on every field, independent of how the Go field name itself was PascalCased.
- Uses pointer types plus `,omitempty` for nullable/optional fields, letting nil distinguish absent/null from a real zero value.
- Shares its shape-inference behavior with this site's TypeScript, Python, and Zod generators, so field-level nullability/optionality decisions are consistent across all four output languages.
Limitations
- PascalCases JSON keys mechanically and doesn't apply Go's common all-caps initialism convention (ID, URL, HTTP); the struct tag is what actually matters for correctness, but the Go-side field name won't match typical Go style guides on its own.
- Field alignment is an approximation of gofmt's column alignment, not a real gofmt run; pipe the output through gofmt if exact formatting matters.
- Always types JSON numbers as float64, matching encoding/json's default; if you need a stricter numeric type (int, int64) for a specific field, that's a manual edit, and doing so means a decimal value in that field at runtime would fail to unmarshal.
- Type inference is purely sample-based: a field that's always a string in your sample but sometimes a number in real data won't be reflected as anything other than what the sample showed.
Examples
Best Practices & Notes
Best Practices
- Run the output through gofmt after pasting it into a .go file to normalize exact spacing and alignment.
- Review every float64 field against your actual API contract; if a field should be a strict integer, change it by hand, understanding that a decimal value would then fail to unmarshal.
- Use the root name option to name the top-level struct after the real entity it represents (Order, User) instead of leaving generated files all titled RootObject.
- Check pointer fields for nil before dereferencing them in your own code, exactly as you would for any Go pointer; the generator marks them nullable, but Go won't stop you from a nil-pointer dereference at runtime.
Developer Notes
Built on a shared shape-inference module (also used by this site's TypeScript, Python, and Zod generators). Go field names are PascalCased per-struct with a local collision guard (two JSON keys that PascalCase to the same name, like "id" and "Id", get disambiguated with a numeric suffix) independent of the type-name collision guard used for hoisted struct names. Numbers are always rendered `float64` regardless of the shared shape's integer/float distinction, since that distinction exists in the shared module for the Python generator's benefit and doesn't apply to Go's `encoding/json` default behavior. Field alignment padding is computed per-struct from the longest field name and longest type name in that struct only, not globally across the whole output.
JSON to Go Struct Use Cases
- Generating request/response structs for a Go HTTP client or server from a real captured payload.
- Typing a config file read into a Go application at startup.
- Bootstrapping structs for a new integration before hand-refining field types and validation.
- Documenting a JSON payload's shape for Go-writing teammates in directly usable Go code.
Common Mistakes
- Changing a float64 field to int without checking whether the real API ever sends a decimal value in that field; encoding/json will fail to unmarshal a non-integer JSON number into an int field.
- Dereferencing a pointer field without a nil check, since a nullable/optional field being nil is exactly what its pointer type is signaling.
- Assuming the PascalCased Go field name needs to look Go-idiomatic (like ID instead of Id) for encoding/json to work correctly; only the json struct tag affects (de)serialization.
Tips
- Pipe the output through gofmt (or your editor's format-on-save) for exact, canonical formatting.
- Pair with the JSON to Zod Schema tool when the same payload is also consumed by a JavaScript/TypeScript service and needs runtime validation there.
- When a struct has several pointer fields, consider whether your sample is representative or whether the API genuinely omits/nulls those fields that often.