Generate Go structs from JSON
Decoding JSON in Go means defining a matching struct with the right field types
and json:"..." tags by hand — tedious and error-prone for nested payloads. This
tool infers typed Go structs from a representative JSON sample so you can
paste them straight into your project.
How it works
The generator walks the sample and maps each value to a Go type, building nested structs as it goes:
| JSON | Go type |
|---|---|
| integral number | int64 |
| fractional number | float64 |
| mixed numeric array | []float64 |
| string | string |
| boolean | bool |
| object | its own exported struct (pointer) |
| array of T | []T |
| mixed array | []interface{} |
Field names are PascalCased, with common initialisms like ID and URL
capitalised the way Go’s style guide expects, and every field gets a
json:"originalKey" tag.
Example
This JSON:
{ "id": 7, "user": { "name": "Sam" } }
generates:
type Root struct {
ID int64 `json:"id"`
User *User `json:"user"`
}
type User struct {
Name string `json:"name"`
}
Because the types are inferred from one sample, treat the output as a strong starting point. All inference happens in your browser — your JSON is never uploaded or stored.
Go’s JSON decoding model — why struct tags matter
Go’s encoding/json package decodes JSON by matching keys to struct field names. Without a json:"..." tag, the decoder matches case-insensitively by default, so name in JSON maps to a field named Name. But case-insensitive matching fails when the JSON key is something like user_id or userId and the Go field is UserID — the conventions diverge.
The generated structs include json:"originalKey" tags on every field so the mapping is explicit and immune to case mismatch or key naming differences. This is Go idiomatic style and follows the recommendations in the standard library documentation.
Type inference rules and edge cases
The generator applies a small set of rules to map JSON values to Go types:
Numbers: A number with no decimal point and no exponent is mapped to int64. A number with a decimal point or exponent is mapped to float64. If an array contains both integral and fractional numbers, the whole array becomes []float64 to avoid type conflicts.
Null values: A JSON null is typed as interface{} because Go has no nullable primitive. In practice, you often want to refine this to a pointer type such as *string or *int64 so the field can hold either a real value or nil.
Mixed arrays: An array containing mixed types — for example [1, "a", true] — falls back to []interface{}. This is correct but rarely useful. If you encounter it, consider whether the API is actually designed to return mixed arrays or whether you need a richer type with custom UnmarshalJSON logic.
Empty objects and arrays: An empty {} becomes map[string]interface{} and an empty [] becomes []interface{}. Paste a sample that contains representative values to get concrete types.
Refining the generated output
After generating, common refinements include:
- Replace
interface{}with a concrete type where you know what the field should hold. - Add
omitemptyto optional fields:json:"fieldName,omitempty"tells the encoder to skip the field when it is the zero value, useful for fields that are not always present. - Convert
int64tointfor small-range values if your codebase style prefers plainintfor counts and indexes. - Add pointer types for nullable fields:
*stringinstead ofstringlets the field represent both a value and the absence of a value (nil).