JSON to Go Struct Converter
Turn a JSON payload into a Go struct with json tags on every field. Keys become exported PascalCase names, initialisms such as ID and URL are capitalised the way vet expects, and the original key stays in the tag so the struct still unmarshals the payload it came from. Paste several samples and the fields missing from some of them pick up omitempty. The ones that were actually null become pointers.
Worked example
{"id":1,"user_name":"ada","last_login":"2024-05-01T10:00:00Z"}
{"id":2,"user_name":"grace","last_login":null}
{"id":3,"user_name":"alan"}becomes
package main
type Root struct {
ID int64 `json:"id"`
UserName string `json:"user_name"`
LastLogin *string `json:"last_login,omitempty"`
}id and user_name appear in all three records, so they are plain fields. last_login is missing from one record and null in another, which is why it gets both a pointer type (a null arrived) and omitempty (a record had no such key). The tag keeps the snake_case key, so the exported Go name does not change what goes on the wire.
Frequently asked questions
Should an optional JSON field be a Go pointer or just omitempty?
They answer different questions. omitempty is an encoding instruction: it keeps a zero value out of the JSON you write. A pointer is a decoding fact: it lets you tell a missing or null value apart from the zero value, because nil is not the same as "" or 0. If you need to know that an int field was absent rather than genuinely zero, use the pointer. The converter turns pointers on for fields that were actually null in your samples, and you can switch that off if your code treats zero values as absent.
When does a JSON number become int64 and when does it become float64?
An integral value maps to int64. A value with a fractional part maps to float64. If the same key is integral in one sample and fractional in another, the merged type widens to float64, since float64 can hold both. An integer past Number.MAX_SAFE_INTEGER is flagged in the review panel: JSON.parse rounded it before any converter saw it, so keep ids like that as strings in the payload if the exact digits matter.
How are JSON keys turned into exported Go field names?
Each key is split into words and rejoined in PascalCase, so user_name becomes UserName. That also makes it exported, which encoding/json requires. Known initialisms (ID, URL, API, HTTP, JSON, URI, UUID, DB) are fully capitalised, and characters that cannot appear in a Go identifier are dropped. If two different keys reduce to the same field name, the second gets a numeric suffix so the struct still compiles, and both keep their own original key in their own tag.
Can I generate nested Go structs from nested JSON?
Yes. Every nested object becomes its own named struct and the parent references it by name, rather than an inline anonymous struct that is awkward to reuse. An array of objects becomes []Name. Two nested objects with the same shape collapse into one struct, so a list of records does not turn into Item1, Item2, Item3.