Skip to content

Formatters & Code

JSON to Go Struct

Idiomatic Go structs with `json:` tags.

Runs in your browser
JSON · source
lines: 17chars: 261size: 261 B
Go struct · result
lines: 16chars: 378size: 378 B
live

Understanding JSON → Go

Struct tags do most of the work.

How Go's encoding/json maps fields, why pointers exist for optionals, and the omitempty trap that catches every Go developer once.

The shape of a Go struct.

A Go struct generated from JSON looks like a record: exported field names (capitalised so the JSON package can see them), a Go type, and a backtick-quoted struct tag that tells encoding/json which JSON key it maps to. The tag is a string literal interpreted by the standard library; without it, Go would use the field name verbatim (which is usually wrong because JSON keys are typically snake_case).

Name string `json:"name"`

Pointers carry the "is this field present?" bit.

Go has no concept of undefined. Every value type has a zero value — 0 for int, "" for string, false for bool. A field of type int with value 0 is indistinguishable from a field that was missing from the JSON. To preserve that distinction, use a pointer: *int is nil when missing, points at zero when the JSON had "x": 0. The cost is the pointer dance everywhere the field is read; the benefit is correct null-vs-absent handling. Mainstream codegen tools choose between pointer and value based on whether the source schema marks the field optional.

The omitempty trap.

The struct tag suffix ,omitempty tells the encoder to drop the field if its value is the type's zero value. Useful for sending optional payloads. Dangerous as soon as zero is a meaningful value — a user setting their age to 0 (a fresh-faced baby), a counter at zero, an empty string that's legitimately empty. The fix is the pointer trick again: *int with omitempty omits only on nil, not on the underlying 0. Every Go developer hits this once and remembers it forever.

A worked example.

From {"id": 7, "name": "Q", "title": null, "tags": ["a"]}, a reasonable inferrer emits a struct with ID int `json:"id"`, Name string `json:"name"`, Title *string `json:"title"` (pointer because it was null), and Tags []string `json:"tags"` (slices are inherently nilable). The ID field gets the standard-library Go convention of an all-caps initialism.

JSON sample

{ "id": 7, "name": "Q", "title": null, "tags": ["a"] }

Each key maps to a struct field with a json tag.

title is null → pointer ; tags is array → []string slice

= ID/Name/Title *string/Tags []string

Time values.

The standard library marshals and unmarshals time.Time as RFC 3339 strings — the ISO 8601 subset most JSON APIs use. If your API returns Unix epoch seconds, you need a custom UnmarshalJSON method (or a wrapper type). Codegen tools often default to string for date-shaped fields and leave the conversion to the consumer; that's safer than guessing wrong and emitting time.Time on a value that doesn't parse.

Maps for dynamic keys.

A JSON object whose keys aren't fixed — a localisation table, a hashmap of feature flags, a per-day metric — should become a map[string]T not a struct. Codegen tools detect this when the same key set varies wildly between samples; if your tool emits an enormous struct with hundreds of fields, the source is probably better modelled as a map.

The decoder's strictness.

By default Go's JSON decoder is lenient: unknown fields in the input are silently ignored. For an internal API that's fine; for a public API or anything you want to catch regressions on, use json.NewDecoder(r).DisallowUnknownFields() which errors when the JSON has a key your struct doesn't. The codegen output is struct-only; the strictness is a runtime decoder choice.

Frequently asked questions

Quick answers.

How does it handle nested JSON objects?

The converter recursively traverses the JSON to create nested Go types. It produces either inline structs or separate named types depending on the complexity of the input.

What happens with null or empty values?

Fields with null values are typically mapped to `interface{}` or pointer types to handle optionality. You should verify these against your specific API requirements to ensure type safety.

Are the struct tags configurable?

The tool generates standard `json:` tags based on the original keys. It automatically sanitises keys that contain hyphens or spaces to ensure they are valid Go identifiers.

Is my JSON payload secure?

Yes. The conversion logic is executed entirely via JavaScript in your browser. No data is transmitted to an external server during the generation process.

People also search for

Related tools

More in this room.

See all in Formatters & Code