Tools
JSON to Go
Paste JSON, get gofmt-clean structs with json tags — pointers for nullable fields, omitempty on optional ones, time.Time for dates. Runs entirely in your browser.
Generated code
More on this site: all tools ·JSON formatter ·regex checker ·the arcade
Beta — the generated code is unit- and compile-tested, but inference from one sample can't be perfect; on rare occasions the output may need a tweak. Spot something wrong?Tell me.
What is this tool?
A free JSON-to-Go converter. Paste a JSON document and it generates exported structs for the whole tree, formatted the way gofmt would leave them: aligned fields, proper Go initialisms (ID, URL, notId, Url), json:"…" tags carrying your original keys, and encoding/json-ready types throughout. Warnings name every place your sample was too thin to type — nothing is guessed silently.
Your JSON never leaves the browser. Inference and generation run client-side; the page works offline once loaded.
How to use it
- Paste JSON on the left — the structs regenerate as you type.
- Name the root struct; nested structs are named from their keys, singularized inside arrays (
users: […]→User). - Choose how nullable fields are expressed: pointers (default) or bare zero values.
- Copy or Download the
.gofile (declared aspackage models— rename to taste).
Pointers or zero values for nullable fields?
Go has no null for value types, so a JSON field that can be null (or absent) forces a choice:
| Mode | Behavior | Cost |
|---|---|---|
| Pointers (default) | *string is nil when the key was null or missing — absence is representable and testable. | Deref noise, and a nil check you must remember. |
| Zero values | string just becomes "", int64 becomes 0. | You can no longer tell "the API sent 0" from "the API sent nothing" — fine for display code, dangerous for business logic. |
omitempty and its gotchas
Fields your sample showed as optional (missing from at least one object) get json:"…,omitempty", so marshaling omits them instead of inventing keys. Two things worth knowing:
omitemptymeans "zero value", not "wasn't set". On a bareint64it also omits a legitimate0; on a baretime.Timeit omits nothing, because a zero struct isn't "empty" toencoding/json. In the default pointer mode optional fields are pointers for exactly this reason — anilpointer is unambiguously empty. In zero-value mode you're accepting these ambiguities knowingly.- Unmarshaling ignores tags you don't have.Unknown incoming keys are silently dropped by
encoding/json— if you need strictness, wrap ajson.DecoderwithDisallowUnknownFields().
Why int64 and float64
Integer fields are typed int64 rather thanint: JSON IDs routinely exceed 2³¹, and plainint is 32-bit on some platforms — the truncation bug you least want to discover in production. Fields where any sample showed a decimal point become float64, which is exactly what encoding/json decodes into anyway. The distinction comes from the raw token: this tool's parser keeps 1 and 1.0 apart whereJSON.parse would erase it.
time.Time and RFC 3339
String fields become time.Time only when every sample matches ISO 8601 with full date — which is the shapeencoding/json natively unmarshals intotime.Time (RFC 3339, e.g.2026-07-03T10:30:00Z). Date-only strings (2026-07-03) are detected too, butencoding/json won't parse those intotime.Time — if your data uses bare dates, keepDetect dates off for Go or use a custom type wrapping time.Parse("2006-01-02", …).
Struct tags carry your real keys
Whatever the JSON key looked like — created-at,user_id, élan — the Go field is a clean exported identifier and the tag preserves the original spelling, so round-trips are exact:
CreatedAt time.Time `json:"created-at"`
UserID int64 `json:"user_id"`The rare key that can't live in a tag (one containing a quote, comma or backtick) is flagged in the warnings instead of being emitted broken.
FAQ
Is it free? Yes — free, no sign-up, no limits.
Is my JSON uploaded anywhere? No — fully client-side, works offline after load; only your last input is kept, in your own browser's local storage.
Why did a field come out any? The sample never showed its type: always null, an empty array, or two values with irreconcilable types. The warnings panel names the exact JSON path. (any is the modern spelling ofinterface — Go 1.18+.)
Does it generate marshal/unmarshal code? It doesn't need to — struct tags are Go's serialization story, and json.Unmarshal(data, &resp) does the rest. Custom UnmarshalJSON methods only earn their keep for exotic shapes.
Can it read a JSON Schema? Not yet — v1 infers from samples; schema input is planned.
Built from scratch for this site in vanilla TypeScript — a pure, unit-tested inference engine with golden-tested emitters and zero runtime dependencies.