JSON to Go Struct: Generate Types With JSON Tags
Generate Go structs from JSON free. Get int64, float64, pointers for optional fields, json tags, and nested types using only the standard library.
To convert JSON to Go, paste a sample into the JSON to Go struct generator, set the package and root type names, and generate. The output is a set of Go structs with exported PascalCase fields, json tags that preserve the original keys, and int64, float64, string, bool, slices and nested structs as the inferred types. It uses only the standard library.
Go's encoding/json needs a destination type, and writing one by hand from a large payload is tedious and easy to get subtly wrong — a missing omitempty, a pointer where it should be a value, a tag that does not match the wire name. Generating from a real response removes most of that work.
What the output looks like
For {"name":"Ada","age":36,"email":null,"tags":["go"],"address":{"city":"London"}}, the generator produces something like:
package main
type Root struct {
Name string `json:"name"`
Age int64 `json:"age"`
Email *string `json:"email,omitempty"`
Tags []string `json:"tags"`
Address Address `json:"address"`
}
type Address struct {
City string `json:"city"`
}
The struct is ready to pass to json.Unmarshal, and the tags keep the JSON keys stable even though Go fields must be exported and conventionally PascalCase.
How to generate Go structs from JSON
- Open the JSON to Go struct generator.
- Paste a representative JSON sample.
- Set the root type name. The default is
Root. - Set the package name. The default is
main. - Press Generate.
- Copy the code into a
.gofile, then rungofmtif your editor does not format on save.
The result reports the number of structs generated, which is a quick check that nested objects became their own types.
Type mapping
| JSON value | Go type |
|---|---|
| String | string |
| Integer | int64 |
| Decimal | float64 |
| Boolean | bool |
| null | any (or a pointer when merged with a real type) |
| Object | A generated struct |
| Array | []T |
| Empty or mixed array | []any |
int64 is the default for integers because JSON numbers have no width and a value can exceed int32. float64 is the only float type the standard library decodes into without a custom unmarshaler. If your domain guarantees a narrower type, change it after generation and test with real values.
Optional fields, pointers and omitempty
The generator merges samples of the same object shape, including array elements. A key that is missing from some samples or null in some becomes optional, and the generated field gets two adjustments:
- A pointer type, such as
*string, so the zero value can be distinguished from "not present". omitemptyin the tag, so marshalling leaves the field out when it is nil.
A purely null field stays any, which already carries nil and needs no pointer. This is the part that matters most in practice: without pointers, an absent number and a real zero look identical after unmarshalling.
If you do not need that distinction, remove the pointer and the omitempty after generating. For a field that should default to a value, keep a value type and handle the default in your code or with a custom unmarshaler.
Field names and tags
Go requires exported fields, so JSON keys are converted to PascalCase: email_address becomes EmailAddress, user-id becomes UserId. The original key is preserved in the tag:
EmailAddress string `json:"email_address"`
That combination is what makes the struct usable: exported names for Go code, exact keys for the wire format. A key starting with a digit is prefixed with N so the field is a legal identifier, and the tag still carries the real name.
Every field gets a tag, not just the renamed ones, so the mapping is explicit and survives a future rename of the Go field.
Root arrays and scalars
A top-level object becomes a struct. A top-level array becomes a slice type:
type Root []Item
A top-level scalar becomes a type alias such as type Root string. Both are valid and easy to change to a named struct if you prefer.
Common problems and fixes
A field is a pointer when it is always present. One merged sample omitted it. Use a uniform sample, or change the field to a value type and drop omitempty.
A field is any when I expected a type. It was null in every sample, or an array mixed incompatible types. Provide a sample with a real value or replace any with the known type.
Numbers lose precision in JavaScript tools but not here. This generator runs in the browser, where JSON parsing uses JavaScript numbers. Integers beyond 2^53 can lose precision before generation. If exact large IDs matter, keep them as strings in the JSON or generate from a smaller sample that preserves them.
The package name is rejected. It is sanitised to a valid identifier, lowercased, with invalid characters replaced. Set a simple name such as main, models or api.
A key became an unexpected field name. Punctuation and acronyms are normalised for a legal Go identifier, with the original key kept in the tag. Rename the field if you prefer.
The JSON will not parse. The input must be strict JSON. Comments, trailing commas and single quotes are rejected; the JSON formatter can locate the syntax error.
Deeply nested payloads stop generating types. Inference is capped at a depth of 24 and 64 structs, and anything beyond becomes any. Generate the upper levels and write the rest by hand.
Tips for better Go structs
- Use a real response. It contains the nulls and optional fields that determine pointers and
omitempty. - Include several array elements. The generator merges their shapes, so two or three variants produce a more accurate result than one.
- Run
gofmt. The generated code is valid, but formatting it with the standard tool keeps it consistent with the rest of the package. - Keep tags. They are the contract with the JSON producer. Removing them because the field names match today creates a silent break later.
- Add validation separately. Go structs describe shape; required fields, ranges and formats need explicit checks after unmarshalling.
- Watch
omitemptyon zero values. A real0orfalseon a value field withomitemptyis omitted when marshalled. That is why optional scalars are pointers here. - Generate types for the other side too. The JSON to Rust struct generator and JSON to Zod schema builder cover the same sample in other ecosystems.
Decoding and encoding
The generated structs work with the standard library:
var root Root
if err := json.Unmarshal(data, &root); err != nil {
return err
}
For encoding, the tags control the output keys, and omitempty drops nil pointers. If you need strict rejection of unknown fields, use a decoder with DisallowUnknownFields() rather than relying on the struct alone. Go ignores unknown keys by default, unlike a strict Zod schema.
Frequently asked questions
Is the JSON to Go generator free?
Yes. There is no account and no charge.
Does my JSON get uploaded?
No. The conversion runs in your browser and the JSON is not stored.
Does it use only the standard library?
Yes. The generated structs work with encoding/json and require no third-party packages.
Why are optional fields pointers?
A pointer distinguishes "missing or null" from a real zero value. Optional fields also get omitempty so they are omitted when marshalling.
Does it generate JSON tags?
Yes. Every field gets a json:"original_key" tag, with ,omitempty added for optional or nullable fields.
Can it handle a top-level array?
Yes. It generates a slice type such as type Root []Item instead of a struct.
Bottom line
A generated Go struct gives you a correct starting point for encoding/json, with the tags and pointer semantics that are easy to forget by hand. Start from a realistic sample, keep the tags, and review pointer fields against what the API actually guarantees. Open the JSON to Go struct generator, and use the JSON to CSV converter if the same data needs to be inspected in a spreadsheet.
Related posts
View allIBAN Validator: Check an IBAN Before You Send Money
One mistyped character can bounce a payment. Check the country, length and mod-97 checksum of an IBAN before you send it.
Base64 Encode and Decode: A Practical Guide
Encode text to Base64 or decode it free in your browser. UTF-8 safe, line breaks tolerated, size and character counts shown, with errors on invalid input.
Convert CSV to JSON: Keep Types and Headers Right
Convert CSV to JSON free with auto delimiter detection, typed numbers and booleans, duplicate-header handling and 2/4-space or tab output. Runs in browser.
Comments (0)
Be the first to share feedback on this post.