JSON → Go

Package:Struct:
JSON Input
Loading editor…
Go Structs
Loading editor…

JSON to Go

Paste any JSON and get Go structs instantly. Nested objects become separate named structs, fields are aligned the way gofmt would format them, and optional or nullable fields use pointer types so you can tell a missing value apart from a real zero value.

Nested structs
Deep objects become separate named structs.
json tags
Every field keeps its original JSON key via a struct tag.
gofmt-aligned
Field names, types, and tags line up in columns.
Client-side
No data is uploaded. Everything runs in your browser.

How JSON Maps to Go Structs

Every JSON object becomes a Go struct. Nested objects generate additional structs named after the key, capitalized to be exported. Arrays of objects generate a struct for the element type, with the key name singularized.

Input JSON:

{
  "userId": 1,
  "isActive": true,
  "address": { "city": "Springfield", "zipCode": "12345" },
  "posts": [{ "id": 101, "title": "Hello World" }]
}

Generated Go:

package main

type Root struct {
	UserId   int     `json:"userId"`
	IsActive bool    `json:"isActive"`
	Address  Address `json:"address"`
	Posts    []Post  `json:"posts"`
}

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

type Post struct {
	Id    int    `json:"id"`
	Title string `json:"title"`
}

Field names are converted to exported PascalCase (userIdUserId), while the json:"..." struct tag preserves the exact original key so encoding/json still unmarshals correctly.

Type Inference and Pointer Fields

Whole numbers become int (or int64 if they exceed the 32-bit range), decimals become float64, strings become string, and booleans become bool. Arrays of objects become []StructName; arrays of a single primitive type become []string, []int, and so on. Mixed-type arrays and empty arrays fall back to []interface{}.

A field that is null in the JSON, or missing from some objects in a merged array, is made a pointer type (*int, *string, *Address, etc.) instead of a value type. This is the idiomatic Go pattern for optional JSON fields — it lets nil represent "absent" distinctly from the type's real zero value (an empty string, a zero int, or false), which a plain value type can't do. Slices are left as-is even when optional, since a nil slice already represents "absent" without needing a pointer.

The omitempty Toggle

With omitempty enabled (the default), every optional or nullable field's tag becomes json:"key,omitempty", which tells encoding/json to skip that field when marshaling if it's at its zero value (nil for pointers and slices). This keeps output JSON clean when re-serializing a struct that was only partially filled in.

Turn omitempty off if you need every field to always appear in marshaled output, for example when a downstream consumer expects a fixed set of keys regardless of whether they're empty.

The Package and Struct fields in the toolbar control the package declaration and the name of the top-level struct — both are sanitized into valid Go identifiers automatically.

Frequently Asked Questions

Why do some fields use a pointer type like *int instead of int?

A field becomes a pointer when it's null in the JSON, or absent from some objects in a merged array. Go value types can't represent "absent" separately from their zero value, so the generator uses a pointer (nil vs. a real value) for correctness. Arrays are left as plain slices since a nil slice already serves that purpose.

Why is the field name capitalized differently from the JSON key?

Go only exports (makes accessible outside the package) identifiers that start with a capital letter, so struct fields are always PascalCase. The original JSON key is preserved exactly in the json:"..." struct tag, so encoding/json still reads and writes the correct key at runtime.

What does omitempty do?

It adds ,omitempty to a field's json tag so encoding/json skips that field during marshaling when it's at its zero value (nil for pointers and slices). It's applied only to fields already marked optional or nullable — required fields are left without it.

Can I change the package name?

Yes, the Package field in the toolbar controls the package declaration at the top of the file. It's sanitized into a valid Go package identifier automatically.

Does this handle deeply nested JSON?

Yes. Each nested object generates its own struct recursively to any depth, in the order encountered, with the top-level struct emitted first.

Is my JSON uploaded anywhere?

No. The entire conversion runs in your browser with no network requests. Nothing is transmitted.

More Tools