Why generate Go structs from a sample?
Go is unforgiving about JSON in a way scripting languages are
not: encoding/json wants a struct whose fields and
tags line up with the payload, and writing that struct by hand
from a real API response — three levels of nesting, an array of
objects with a field that only sometimes appears — is slow,
typo-prone work. The sample already contains every fact the
struct needs. This converter extracts them mechanically: paste
the response, get back compilable struct definitions with the
JSON tags filled in, and spend your own time on the modelling
decisions only you can make.
How to use this tool
- Paste the JSON. A real API response is ideal; the more representative the sample — edge cases, empty arrays, optional blocks — the more truthful the structs.
- Name the root struct.
Rootis fine for a quick look; for code you will keep, use the name it will wear in your project (OrderResponse,UserProfile). - Press Generate Go. The root struct comes first, the structs it references after it.
- Read the notes if any appear. They list every slot that had to become
interface— a null, a mixture of types, an empty array — and say which, so nothing was decided silently. - Copy or download the result, then tighten it: swap in
time.Time,json.RawMessageor domain types where your knowledge beats the sample's evidence.
The rules it follows
Naming. Structs are PascalCase after the key
that holds them; fields are PascalCase as Go requires, with the
original key preserved exactly in the json tag.
Merging. Array elements are treated as
sightings of one struct: keys are unioned, and a key absent from
any element is marked ,omitempty instead of
spawning a second struct. Numbers. All-whole
numbers become int64; any fraction widens the slot
to float64. Honesty. Nulls, mixed
slots and empty arrays become interface — and
each one is reported in the notes above the result, never
quietly. A string that looks like a date stays
string: JSON has six types, and the generator
reports the shape the data has, not the meaning you might
project onto it.
Worked example
Given this sample (the second user has no nickname):
{
"team": "Platform",
"users": [
{ "id": 1, "name": "Ada", "nickname": "ada" },
{ "id": 2, "name": "Grace" }
]
} the converter emits:
type Root struct {
Team string `json:"team"`
Users []User `json:"users"`
}
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Nickname string `json:"nickname,omitempty"`
}
The omitempty is the second user talking: the field
demonstrably comes and goes, so the tag says so.