JSON to Go struct — typed structs with json tags from a sample

Paste a sample JSON response and get Go struct definitions with json tags, Go-style field names such as OrderID, a named type for each nested object, and omitempty on fields that only some array items have.

Live demo · real result from this tool

Go

type User struct {	ID        int64    `json:"id"`	Name      string   `json:"name"`	Email     string   `json:"email"`	Active    bool     `json:"active"`	Roles     []string `json:"roles"`	Address   Address  `json:"address"`	LastLogin any      `json:"lastLogin"`} type Address struct {	City     string `json:"city"`	Postcode string `json:"postcode"`} 

Processed on your device — nothing is uploaded.

How to use JSON to Go Struct

  1. Paste a representative sample into JSON. For a list, paste an array with several items so the tool can see which fields are optional.
  2. Set the Struct name for the top-level type.
  3. Tick Add omitempty to every tag if empty values should be dropped when you marshal the struct.
  4. Tick Inline nested structs for anonymous struct types instead of separate named types.
  5. Keep Use pointers for nullable fields ticked to use pointer types where the sample has nulls. Copy or download types.go.

What it does and when to use it

Before you can json.Unmarshal an API response in Go, you need structs that match it. Writing them by hand for a large payload is slow, and a single mistyped tag silently leaves a field empty. Paste one real response here and you get a starting point you can drop into your package, then adjust.

It suits webhook payloads, third-party API clients, config files and test fixtures. For the same sample in other languages, see JSON to TypeScript and JSON to Python. If the sample does not parse, fix it first with JSON repair.

How it works

The tool infers a shape from the whole sample. For an array, every item is merged, so a field missing from some items is marked optional and gets ,omitempty in its tag. Types map as follows: numbers written without a decimal point or exponent to int64 (or json.Number when they do not fit int64, with a note to import encoding/json), other numbers to float64, strings to string, booleans to bool, arrays to slices of the merged item type, and objects to their own struct, named after the key in singular form (items gives Item). Fields are aligned the way gofmt does. Nothing is sent anywhere; the code is built in your browser.

Worked examples

An order with a nested customer, a list of items and an empty list (struct name Order):

type Order struct {
	OrderID  string   `json:"order_id"`
	Total    float64  `json:"total"`
	Qty      int64    `json:"qty"`
	Paid     bool     `json:"paid"`
	Coupon   any      `json:"coupon"`
	Customer Customer `json:"customer"`
	Items    []Item   `json:"items"`
	Tags     []any    `json:"tags"`
}

type Customer struct {
	ID    int64  `json:"id"`
	Email string `json:"email"`
}

type Item struct {
	Sku   string  `json:"sku"`
	Price float64 `json:"price"`
	Gift  bool    `json:"gift,omitempty"`
}

Price is float64 because one item has 9.5. Gift is optional because only one item has it.

A root array of users where nick is null in one item gives type Users []User and the field Nick *string.

Limits and tips

  • Integers too large for int64 are still typed int64. Use uint64, json.Number or a string for such IDs.
  • any needs Go 1.18 or later; on older Go, replace it with interface{}.

Frequently asked questions

Why is a field typed any?
The generator only knows what the sample shows. A field that is always null, an empty array ([]any), or a field whose type changes between items (a number in one, a string in another) becomes any. Replace it with the real type once you know it.
Why is my price an int64?
Every value of that field in your sample was written as a whole number, so the tool picked int64. A value written with a decimal point, such as 1.0, gives float64. Go's encoding/json refuses a later value like 9.99 for an int64 field, so include a decimal value in the sample, or change the type to float64 by hand.
When does a field get a pointer?
With "Use pointers for nullable fields" ticked, a field that is null in some items and has a real value in others becomes a pointer, such as *string, so you can tell null from an empty string. Untick it to get the plain type, where null decodes as the zero value.
What do the field names look like?
Keys are split on underscores, dashes and case changes and joined in PascalCase, with common initialisms upper-cased (ID, URL, API, HTTP, JSON, UUID and others), so api_url becomes APIURL. A name that would start with a digit gets an N in front, so 2fa becomes N2fa. The json tag always keeps the original key.

Written by the ToolsRift team · Last updated

Pages are drafted with AI assistance and checked by automated tests. How we write and check pages.

Was this tool useful?

Report a problem

Start typing to search every tool.

↑ ↓ to moveEnter to openEsc to close