JSON to Go Struct

Generate Go structs with json tags from JSON instantly. Handles nested objects, arrays, nullable pointers, and omitempty tags. Free, runs in your browser.

  • Runs in your browser
  • Your data never leaves your browser
  • Free · No Sign-Up
A blank name uses RootObject. Click Generate Go Struct to apply a changed name.
Generate now with the current JSON and root name. Ctrl/⌘+Enter also generates.
Replace JSON with a sample containing nested objects, arrays and null, then generate immediately with the current settings.
Clear JSON, output and status. Keep the root name. Ctrl/⌘+L with focus in the tool also clears the root name.
Enter valid JSON without comments or trailing commas. Generation runs 300 ms after typing stops; invalid JSON clears the output and shows an error.
Go Output
Copy the complete displayed Go output. Empty output is not copied.

Enter JSON or load the example to generate Go.

Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.

Type Mapping

  • null → interface{}
  • string → string
  • number without . or exponent → int
  • number with . or exponent (19.0, 1e3) → float64
  • boolean → bool
  • array → []T
  • nullable/optional → pointer (*T)
  • nested object → separate named struct

Example

Given this JSON:

{"name": "Alice", "age": 30, "address": {"city": "London"}}

The tool generates:

type RootObject struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Address Address `json:"address"`
}

type Address struct {
	City string `json:"city"`
}

Example: An API Response

{
  "user": {
    "id": 42,
    "name": "Alice",
    "email": "alice@example.com",
    "is_active": true,
    "roles": ["admin", "editor"],
    "address": { "city": "New York", "country": "US", "zip_code": "10001" },
    "last_login": null
  }
}

generates

type RootObject struct {
	User User `json:"user"`
}

type User struct {
	Id int `json:"id"`
	Name string `json:"name"`
	Email string `json:"email"`
	IsActive bool `json:"is_active"`
	Roles []string `json:"roles"`
	Address Address `json:"address"`
	LastLogin interface{} `json:"last_login"`
}

type Address struct {
	City string `json:"city"`
	Country string `json:"country"`
	ZipCode string `json:"zip_code"`
}

snake_case keys become CamelCase field names, and the json tag keeps the original key, so encoding/json maps them both ways. The fields are not aligned; run gofmt (or save in an editor that runs it) to line up the tags. Decode with the standard library:

var root RootObject
if err := json.Unmarshal(data, &root); err != nil {
	log.Fatal(err)
}
fmt.Println(root.User.Name) // Alice

Example: A Top-Level Array

[{"sku": "A1", "qty": 2}, {"sku": "B2", "note": "gift"}]

generates

type RootObject struct {
	Sku string `json:"sku"`
	Qty *int `json:"qty,omitempty"`
	Note *string `json:"note,omitempty"`
}

For a top-level array, the struct describes one element; decode into []RootObject. Keys missing from some elements become pointers with omitempty.

Example: Same Key Twice, Decimals, and a Key Starting With a Digit

{
  "order": { "id": "A-1001", "total": 19.0, "meta": { "createdBy": "alice", "source": "web" } },
  "payment": { "status": "paid", "meta": { "provider": "stripe", "fee": 0.3 } },
  "2fa": true
}

generates

type RootObject struct {
	Order Order `json:"order"`
	Payment Payment `json:"payment"`
	X2fa bool `json:"2fa"`
}

type Order struct {
	Id string `json:"id"`
	Total float64 `json:"total"`
	Meta Meta `json:"meta"`
}

type Meta struct {
	CreatedBy string `json:"createdBy"`
	Source string `json:"source"`
}

type Payment struct {
	Status string `json:"status"`
	Meta PaymentMeta `json:"meta"`
}

type PaymentMeta struct {
	Provider string `json:"provider"`
	Fee float64 `json:"fee"`
}

payment.meta has different fields from order.meta, so it gets its own struct named with its parent in front, PaymentMeta; with the same fields, both would share Meta. 19.0 is written with a decimal point, so total is float64: encoding/json refuses to decode 19.0 into an int field. The tool reads the number as written through the browser’s JSON source text access (Chrome 114+, Firefox 135+, Safari 18.4+); browsers without it see 19 and fall back to int. The key 2fa cannot start an exported Go name, so the field is X2fa and the tag keeps 2fa.

What to Fix After Generating

  • null becomes interface{}. Change it to a pointer of the real type, such as *string or *time.Time, after checking the API docs.
  • A number written without . or an exponent becomes int, and 19.0 or 1e3 becomes float64; integers and decimals mixed in one array or key give float64. A sample that happens to hold only whole numbers still gives int, so check fields such as prices. int is 64 bits on 64-bit platforms.
  • [] and arrays with other mixed element types become []interface{}.
  • Field names are not adjusted to Go initialisms: id becomes Id and url becomes Url, while Go Code Review Comments recommends ID and URL. The json tag keeps decoding correct either way.
  • A key whose field name would not start with an upper-case letter (2fa, 名前) gets an X prefix (X2fa), and two keys that give the same name (user_id, userId) get a number (UserId2). An empty key and keys with characters a struct tag cannot hold (such as " or ,) are listed in a comment instead of a field, because encoding/json cannot map them by tag.
  • Generated names such as PaymentMeta or Meta2 come from the JSON keys; rename them to match your domain.
  • Only json tags are written. Add gorm, bson, or validate tags yourself.

Limits

  • The input must be valid JSON; the error message gives the position, for example Expected double-quoted property name in JSON at position 8 for a trailing comma.
  • Types come only from the sample you paste.

FAQ

What does this tool generate?

It generates Go struct type declarations with json struct tags. Each nested JSON object becomes its own named struct. Array fields become slices ([]T).

How are nullable fields handled?

A key whose only value in the sample is null becomes interface{}, because the sample does not show its type. In an array of objects, a key that is null in some items and has a value in others becomes a pointer to that type (for example *string), and a key that is missing from some items becomes a pointer (a slice stays a slice) with ,omitempty in its json tag.

Why are pointer types used?

In Go, pointers are the idiomatic way to represent optional or nullable values. A *string can be nil (absent/null) whereas a string cannot.

What json tags are generated?

Every field gets a json tag with the original JSON key, so snake_case and camelCase keys still map after the field gets an exported Go name. Keys that are missing from some items of an array also get ,omitempty. An empty key and keys that contain characters a struct tag cannot hold, such as a double quote or a comma, are written as comments instead of fields. Only json tags are generated.

Is my data sent to a server?

No. The structs are generated in your browser tab, and the JSON and the root struct name are not sent to a server or saved in browser storage. When you finish editing the input, click Generate Go Struct or load the example, the page's analytics records one usage event with the tool name and the action (generate), not the JSON or the code.