json

FormatValidateConvert

JSON to Go

JSON
Language
Structured output

Result· read-only

—Go

The result appears here.

Generate

JSON to Go: generate structs from JSON.

Your document never leaves the browser.

Go structs with json tags, from a JSON sample — in your browser, never uploaded.

Paste the JSON an API returns and get structs that encoding/json unmarshals it into. Field names follow Go’s conventions, and every field keeps its original key in a json tag.

OrderID

not OrderId: Go’s initialisms are kept

json.Number

for an integer past int64, so no digit is rounded

0

bytes leave your machine

Tags, pointers and initialisms

Each object becomes a struct and each key an exported field, with the JSON name in its tag. Go’s initialisms are respected, so order_id becomes OrderID, not OrderId. Whole numbers are int64 and numbers with a fraction float64, and the fields are aligned the way gofmt aligns them.

gift-wrap is missing from one line item, so by default it is *bool with omitempty: nil means the key was not there, and a false you set is still written out. note is sometimes null and sometimes a string, and Go has no nullable string, so it is any, with a comment listing nil and string as the values that were seen.

1

The sample, an order with two line items, pasted as the source

{
  "order_id": 1042,
  "placed_at": "2026-09-25T10:15:00Z",
  "paid": true,
  "customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
  "items": [
    { "sku": "PEN-01", "qty": 2, "price": 3.5, "note": null },
    { "sku": "INK-07", "qty": 1, "price": 12, "note": "Fragile", "gift-wrap": true }
  ]
}
2

The structs written for it

package main

type Customer struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type Item struct {
	Sku      string  `json:"sku"`
	Qty      int64   `json:"qty"`
	Price    float64 `json:"price"`
	Note     any     `json:"note"` // one of: nil, string
	GiftWrap *bool   `json:"gift-wrap,omitempty"`
}

type Root struct {
	OrderID  int64    `json:"order_id"`
	PlacedAt string   `json:"placed_at"`
	Paid     bool     `json:"paid"`
	Customer Customer `json:"customer"`
	Items    []Item   `json:"items"`
}

Options

The sample, with Optional fields omitempty only

package main

type Customer struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type Item struct {
	Sku      string  `json:"sku"`
	Qty      int64   `json:"qty"`
	Price    float64 `json:"price"`
	Note     any     `json:"note"` // one of: nil, string
	GiftWrap bool    `json:"gift-wrap,omitempty"`
}

type Root struct {
	OrderID  int64    `json:"order_id"`
	PlacedAt string   `json:"placed_at"`
	Paid     bool     `json:"paid"`
	Customer Customer `json:"customer"`
	Items    []Item   `json:"items"`
}

Option

Package

Package: main by default. Type the package the file will live in.

Option

Optional fields

Optional fields: *T, omitempty, the default, or omitempty only, which keeps plain value types and gives up telling a missing key from a zero value.

When a number is too big

An integer past int64 is typed json.Number, and the file imports encoding/json for it, so the digits arrive as text and nothing is rounded. Call its String method to keep the value exact, or Int64 once you know it fits.

Nested structs take their names from their keys, customer giving Customer, and a slice of objects takes the singular, so items is []Item. A list holding more than one type is []any with a comment naming its element types, and a key starting with a digit gets a letter in front, so 2fa becomes F2Fa. Check a number that happened to be whole in your sample but can carry a fraction elsewhere: it will be int64 here, and unmarshalling 2.5 into it fails.

1

A 20-digit account number, a key starting with a digit, and a mixed list

{ "account": 12345678901234567890, "2fa": true, "codes": [1, "A"] }
2

json.Number with its import, F2Fa and []any

package main

import "encoding/json"

type Root struct {
	Account json.Number `json:"account"`
	F2Fa    bool        `json:"2fa"`
	Codes   []any       `json:"codes"` // elements: int64, string
}

Your sample stays here

Inference and code generation both run inside this browser tab. The sample is never uploaded, stored on a server or logged, because the page has no server to send it to, and once loaded it carries on working with the connection off.

Read next:

FAQ

Frequently asked questions

Didn’t find your answer?Write to us on the contact page →
How do I use the structs?

Declare a variable of the root type and pass its address to json.Unmarshal, or to a json.Decoder reading the response body.

Why is a field typed any?

Because its values differed in type between records, or it was null where others were text. Replace any with the type you expect once you know it.

Does it write struct tags for YAML or BSON?

No, only json tags. Adding a yaml or bson tag beside each one is a quick edit in most editors.

Keyboard shortcuts

Send feedback

Questions, bug reports and feature requests are all welcome. A bug report is easiest to act on with the shape of the document that caused it — never send anything confidential.

Email us

Contact page, in a new tab, so this page stays as it is.

Settings

Indent

The result is written with it — YAML and XML at 2 spaces when it is Tab.

Code text size
14 px

Both panes.

Wrap long lines

Load from a URL

Your browser fetches it directly — the request goes to that site, never to us.