JSON to Go Struct

The JSON to Go Struct Generator converts a JSON sample into Go struct definitions with json: field tags, pointer types for nullable fields, and slice types for arrays. Use it to rapidly generate the structs needed for json.Unmarshal when consuming REST APIs, processing webhook payloads, or building Kubernetes operators.

S. Siddiqui

Edited by

S. SiddiquiFounder & Editor-in-Chief
Sources:MDN Web DocsW3CIETFUpdated Jun 2026

What Is the JSON to Go Struct Generator?

The JSON to Go Struct Generator analyses a JSON sample and produces Go struct definitions with json: field tags, ready to use with Go's standard encoding/json package. Each JSON object becomes a Go struct, each key becomes a named field with the appropriate Go type, and each field includes a json:"fieldName" tag that maps the Go field name to the JSON key during marshalling and unmarshalling.

Go's type system is explicit and static. Working with JSON in Go requires defining structs that match the expected JSON shape before you can unmarshal a response — unlike Python or JavaScript where you can access untyped dictionaries or objects at runtime. Without a struct definition, you must use map[string]interface{}, which loses type safety and requires type assertions for every value access. A properly defined struct with JSON tags allows json.Unmarshal() to parse the JSON and populate a typed Go value directly.

According to the Go standard library documentation for encoding/json, struct field tags control how JSON keys map to struct fields during encoding and decoding. The omitempty tag option instructs the encoder to omit the field if its value is the zero value for its type. The generator applies this convention automatically for fields that appear to be optional in the sample.

This generator is used by Go developers integrating REST APIs, building CLI tools that consume JSON feeds, writing Kubernetes operators (which extensively use Go structs for resource definitions), and developing microservices that exchange JSON over HTTP or message queues.

How to Use the JSON to Go Struct Generator

  1. Paste your JSON sample. The input should be a representative JSON object or array. For API responses that sometimes include optional fields, provide a sample that includes all possible fields — including null values — so the generator can produce correct pointer types for optional fields.
  2. Choose a root struct name. Enter a PascalCase name for the top-level struct — for example User, Product, or APIResponse. Go convention uses PascalCase for exported (public) identifiers. Nested objects generate additional structs named from the property name.
  3. Review type mappings. JSON strings become string. JSON numbers become int64 or float64. JSON booleans become bool. JSON null values become pointer types (*string, *int64) so they can represent both a value and nil. Arrays become slices ([]string, []User).
  4. Check omitempty tags. Fields that were null or absent in the sample receive json:"fieldName,omitempty". Fields that are always present receive json:"fieldName". Review these and adjust where needed based on your API's actual behaviour.
  5. Copy the output. Paste the generated structs into your Go source file. Import encoding/json and use json.Unmarshal(data, &myStruct) to populate the struct from a JSON byte slice.

Why Use This Tool

For any non-trivial JSON structure — more than a handful of fields, nested objects, or arrays of objects — writing Go structs by hand is time-consuming and error-prone. JSON field names are often camelCase or snake_case, Go field names must be PascalCase for exported identifiers, and every field needs both the correct Go type and the correct JSON tag. This tool handles all of that mapping automatically.

Go developers consuming REST APIs

Any Go service that makes HTTP requests to a REST API needs struct definitions matching the response shape before it can use json.Unmarshal effectively. This is the most common use case — pasting a real API response sample and generating the structs needed to parse it correctly in production code.

Kubernetes operator developers

Kubernetes operators are written in Go and define custom resource types as Go structs. The Kubernetes API and the custom resource definitions it manages exchange JSON. Developers building operators frequently need to produce or consume JSON structures matching Kubernetes API objects. This generator provides a starting point for those struct definitions, which are then refined with Kubernetes-specific annotations.

CLI tool developers

Go is popular for building CLI tools, many of which consume JSON from APIs, configuration files, or command output. A developer building a CLI tool that processes GitHub API responses, AWS CLI JSON output, or Terraform state files uses this generator to produce the struct definitions needed to work with those JSON structures in a type-safe way.

Microservice developers

Go microservices commonly communicate via JSON over HTTP or message queues. When a new service needs to consume messages from an existing service, the developer needs Go struct definitions matching the message format. This generator produces those definitions from a sample message, eliminating manual transcription and tag formatting.

Real-World Use Cases

Back-end developer consuming a GitHub REST API response

A Go developer builds a tool that queries the GitHub REST API to generate repository activity reports. The GitHub API returns detailed JSON objects for repositories, commits, and pull requests. Rather than writing each struct definition from the API documentation, the developer calls the API once in curl, copies the JSON response into this generator, and produces the Go struct hierarchy in seconds. The generated structs — Repository, Owner, License, Permissions — are pasted into a models.go file and used with json.Unmarshal to parse subsequent API calls.

Kubernetes operator developer defining custom resource types

A platform engineer builds a Kubernetes operator that manages database backup jobs. The operator's custom resource definition (CRD) includes a spec with scheduling, retention, and storage configuration. The engineer prototypes the spec as a JSON object, pastes it into this generator to produce the initial Go struct definitions, and refines them with Kubernetes controller-runtime annotations. The generated struct provides the correct field names and types as a validated starting point, reducing errors in the CRD spec definition.

CLI developer processing AWS CLI JSON output

A DevOps engineer writes a Go CLI tool that queries AWS for EC2 instance details, filters and formats the data, and outputs a cost summary. The AWS CLI returns complex nested JSON. The engineer pipes one AWS CLI output into this generator, produces the EC2 instance struct hierarchy, and uses it with json.Unmarshal in the Go tool. The resulting code is statically typed — all field access is verified at compile time — unlike a shell script that would process the same JSON with jq field selectors checked only at runtime.

Developer integrating a payment gateway webhook

A Go developer processes Stripe webhook events in a web service. Stripe's event payloads are complex nested JSON. The developer captures a real webhook event from the Stripe CLI, pastes it into this generator, and produces Go structs for the event and its nested data objects. The structs are used in the webhook handler to unmarshal events in a type-safe way, ensuring that all accessed fields are checked at compile time and that webhook handling failures are caught during development rather than in production.

Common Mistakes and Troubleshooting

Using int instead of float64 for JSON numbers

Go's encoding/json package unmarshals all JSON numbers into float64 by default when the target type is interface{}. When unmarshalling into a typed struct, integer JSON values unmarshal correctly into int, int64, or uint64 fields. However, if a field is sometimes an integer and sometimes a float in the JSON, using int64 will cause an unmarshal error when a float value arrives. Use float64 for any field that might have decimal values.

Not using pointer types for nullable fields

If a JSON field is sometimes null and sometimes a value, the Go field must be a pointer type (*string, *int64) to represent both states. A non-pointer string cannot be nil — when json.Unmarshal encounters a null JSON value for a non-pointer field, it sets the field to the zero value (empty string, 0, false) rather than indicating nullness. The generator marks null-valued fields as pointers; verify that non-null required fields are not pointers unless they need to be.

Incorrect handling of JSON arrays at the root level

If the top-level JSON value is an array rather than an object, unmarshal into a slice: var items []Item; json.Unmarshal(data, &items). The generator produces a struct for the array element type. To unmarshal a root-level array, declare the slice and unmarshal directly into it without wrapping in a container struct.

Field names not matching JSON keys due to capitalisation

Go requires exported struct fields (those accessible outside the package) to start with a capital letter, but JSON keys are commonly lowercase or camelCase. Without the json:"keyName" tag, encoding/json does a case-insensitive match — UserID matches userid, userId, and UserID in the JSON. The generator adds explicit json: tags for every field to ensure exact matching regardless of case differences. Always use the generated tags rather than relying on case-insensitive matching in production code.

Omitting the omitempty tag when marshalling

When marshalling a Go struct back to JSON, zero-value fields ("", 0, false, nil) are included in the output unless the field has omitempty in its JSON tag. This means a struct with 20 fields will always produce a JSON object with 20 keys, even if most have zero values. Add ,omitempty to the JSON tag of fields that should be excluded when empty: json:"email,omitempty".

Last reviewed: June 7, 2026

Frequently Asked Questions

What Go types are generated for each JSON value type?
JSON strings become Go string. JSON integers become int64. JSON floats become float64. JSON booleans become bool. JSON null values become pointer types (*string, *int64, etc.) to represent the null state as Go nil. JSON objects become named structs. JSON arrays become slices ([]string, []int64, []User). An empty JSON array produces []interface{} as a conservative type that should be manually refined once the element type is known.
What are JSON struct tags in Go and why are they needed?
Go struct tags are string literals attached to struct fields that provide metadata to packages. The encoding/json package uses json:"fieldName" tags to map between Go field names (which must start with a capital letter for exported fields) and JSON key names (which are typically camelCase or snake_case). Without tags, encoding/json uses the Go field name verbatim — UserId becomes 'UserId' in JSON, not 'userId'. Tags ensure exact key mapping regardless of naming conventions.
How do I unmarshal JSON into the generated struct?
Import encoding/json and use json.Unmarshal: var user User; err := json.Unmarshal([]byte(jsonString), &user). For HTTP responses: var user User; err := json.NewDecoder(resp.Body).Decode(&user). For root-level JSON arrays: var users []User; err := json.Unmarshal(data, &users). Always check the returned error — Unmarshal returns an error if the JSON is malformed or if value types don't match the struct fields.
What is the omitempty tag option?
Adding ,omitempty after the field name in a JSON tag (json:"email,omitempty") tells encoding/json to omit the field from the JSON output when marshalling if the field has its zero value: empty string for strings, 0 for numbers, false for booleans, nil for pointers and slices. Fields with omitempty are still populated during unmarshalling — the option only affects marshalling (Go to JSON). Use it for optional fields that should not appear in the JSON output when they have no value.
How does the generator handle nested JSON objects?
Each nested JSON object produces a separate named Go struct. The struct name is derived from the Go field name converted to PascalCase — an address field produces an Address struct, and userProfile produces a UserProfile struct. The parent struct references the nested struct by name: Address Address. All generated structs must be in the same package (or imported) for the field type references to resolve.
Why are some fields pointer types like *string instead of string?
Pointer types (*string, *int64) allow a field to represent three states: a non-nil value, a nil (representing JSON null), and the zero value of the type. A plain string field can only represent two states: the empty string and a non-empty string — it cannot represent null. If a JSON field is sometimes null, the Go struct field must be *string to avoid losing the null distinction during unmarshal. Access a pointer field with a nil check: if user.Email != nil { fmt.Println(*user.Email) }.
How do I handle a JSON array at the root level in Go?
If the top-level JSON is an array, declare a slice of the element type and unmarshal directly: var users []User; err := json.Unmarshal(data, &users). You do not need a wrapper struct. The generator produces the User struct for the element type. For HTTP streaming of large arrays, use json.NewDecoder(resp.Body) with Token() and Decode() to process elements one at a time without loading the full array into memory.
Which is better: json.Unmarshal or json.NewDecoder?
Use json.Unmarshal when you have the full JSON as a []byte in memory — it is simpler and slightly faster for small payloads. Use json.NewDecoder when reading from an io.Reader (such as an HTTP response body or a file) because it streams the JSON without requiring the full content to be buffered first. For HTTP responses, json.NewDecoder(resp.Body).Decode(&target) is the idiomatic approach. Both produce identical results for the same input.
How are JSON keys with underscores or hyphens handled in Go?
JSON keys with underscores (created_at) or hyphens (x-request-id) cannot be used directly as Go field names. The generator converts them: underscores trigger PascalCase conversion (created_at becomes CreatedAt with json:"created_at"), and hyphens are removed with capitalisation (x-request-id becomes XRequestId with json:"x-request-id"). The JSON tag preserves the original key name for correct mapping during unmarshal.
Can I use the generated structs with Kubernetes controller-runtime?
The generated structs provide a starting point for Kubernetes custom resource types. Kubernetes CRD types require additional markers: embedding metav1.TypeMeta and metav1.ObjectMeta, adding // +kubebuilder:object:root=true comments, and implementing the runtime.Object interface via DeepCopyObject(). After generating the base struct from your JSON spec, follow the Kubebuilder or Operator SDK documentation to add the required Kubernetes-specific boilerplate.

Rate This Tool

Was this tool helpful?

Be the first to rate this tool

About the Author

S. Siddiqui

S. Siddiqui

Founder & Editor-in-Chief

LinkedIn Profile

S. Siddiqui is the founder and editor-in-chief of YourToolsBase, overseeing all content, tool accuracy, and editorial standards.

View full profile

Authoritative Sources

Formulas and data in this tool are based on guidelines from the above sources.