JSON to Go Struct

Paste a JSON object and get the Go structs for it: one struct for each object, a slice for each list, and a json tag that keeps each name as it was written.

Free Runs in your browser Checked Thursday, November 12, 2026

The whole JSON text, with braces at the top. Names keep their order and numbers keep their digits. Nothing is sent or stored.

The name of the outer struct. Use letters, digits and underscores, and start with a letter.

Adds the omitempty option, so encoding/json leaves a field out of its output when the field is empty.

Result

Go code — Copy it, or download it as models.go.
Check — Green when the JSON converts. Red names the place and the reason.
Go code

This tool runs in your browser. What you enter is not sent to us.

How to use it

  1. Paste a JSON object into JSON object. The whole text must be one object, with braces at the top.
  2. Type a Root struct name, such as Product, and tick Add omitempty to every tag if you want that option.
  3. Read Check. Green means the object converted; red names the place where the problem is.
  4. Copy the Go code into a file that has a package clause, or download it as models.go.

How the Go types are chosen

Each JSON value gets the Go type that holds it. A string becomes string, and true or false becomes bool. The Unmarshal rules of encoding/json decide how the JSON is read back into these types.

  • A whole number that fits in 64 bits becomes int64. A number with a point or an exponent, such as 1.0 or 2e3, becomes float64, and so does a whole number too large for int64.
  • A null becomes any. A null that sits beside a value of another type takes that type, because a null leaves a Go value of another type unchanged.
  • An object becomes a struct, and a list takes the type its items share. Objects in one list merge into one struct, and a list of mixed types becomes []any.
  • An empty object becomes an empty struct, and an empty list becomes []any.

Names, tags and clashes

Each field takes its name from the JSON name: the words are joined and each one starts with a capital letter, so user-name becomes UserName. The Go specification exports a field whose name starts with an upper-case letter, which is why the first letter is capitalised. The json tag keeps the name as it was written, so the same key is matched when the JSON is read back.

Two names that give the same Go name get a number, such as AB and AB2, and a struct whose name is already used gets a number too. A list item is named from its list, so products gives a struct named Product, and a name with no plural rule gets the suffix Item.

  • A name with a comma, a single dash or no characters cannot be a json tag, so the tool names that key and stops.
  • With omitempty on, every tag gets the option. The tool capitalises the first letter of the root struct name, so product becomes Product.

What the tool does not do

  • It does not add a package clause or imports. Paste the code into a file that has its own package clause.
  • It does not use pointers for optional fields. A field that is missing or null in the JSON is not told apart from one that holds the zero value.
  • It does not change names to Go's common initialisms, so id becomes Id. Rename the field by hand if your code style wants ID.

Worked example: an order with an owner and two items

The JSON below has a whole number, a decimal, an object and a list of two objects. The table shows the Go field that each JSON name becomes. The tool writes the three structs under the table, with the outer struct Order first.

JSON name Go field Go type Tag
id Id int64 json:"id"
ratio Ratio float64 json:"ratio"
owner Owner Owner json:"owner"
items Items []Item json:"items"

Frequently asked questions

Why is a whole number an int64 and not an int?

The int64 type is a fixed 64-bit signed integer, and it holds every whole number from -9223372036854775808 to 9223372036854775807. The tool uses it for every whole number that fits, so a value does not overflow. Change the type to int by hand if your code needs that.

Why does a null become any?

Go has no type that holds a null by itself, so the tool uses any, which holds any value. A null next to a value of another type takes that type instead, because encoding/json leaves a Go value of another type unchanged when it reads a null.

Why is my field called Id and not ID?

The tool capitalises the first letter of each word and does not apply Go's common initialisms, so id becomes Id. The json tag still reads id, so the data is read the same way. Rename the field if your code style asks for ID.

Which Go version does the output need?

The output uses any for a null, and any is an alias for interface{} that was added in Go 1.18. If your code is older, replace any with interface{}, which is the same type.

Why does the tool refuse some names?

A json tag holds the name, followed by options that start after a comma, so a name with a comma cannot be written in a tag. A tag with a single dash hides the field, so that name is refused as well.

Is the JSON I paste sent anywhere?

No. The conversion runs in your browser, and nothing you paste is stored or sent to our server. Do not paste a password or a token into any page you do not trust.

Sources

Figures and text last checked on Thursday, November 12, 2026.

We use necessary cookies to run the site. With your consent, Google also uses advertising cookies to show personalised ads. If you reject them, you still see ads, but they are not personalised.