---
url: https://findutils.com/guides/json-to-go-struct-guide
title: "JSON to Go Struct: Generate Go Types From a JSON Sample, and What to Fix Before You Use Them"
description: "How to turn a JSON response into Go structs online: what each option does, how types are inferred, and the five things to check by hand (numbers, null, arrays, field names, repeated objects). Free, in your browser."
category: developer
content_type: guide
guide_type: subtopic
cluster: json
locale: en
read_time: 8
status: published
author: "olgunozoktas"
published_at: 2026-10-24T15:08:00Z
excerpt: "JSON to Go Struct reads one JSON sample and writes Go struct types with json tags. This guide shows each option with real output, explains exactly how every JSON value becomes a Go type, and lists the cases the generator cannot know from a single sample: whole-number floats, null, mixed arrays, keys that are not valid Go names, and two objects with the same key."
tag_ids: ["go", "golang", "json", "struct", "developer-tools"]
tags: ["Go", "Golang", "JSON", "Struct", "Developer Tools"]
primary_keyword: "json to go struct"
secondary_keywords: ["convert json to golang struct", "go struct from json response", "golang json struct tags", "json to go struct omitempty", "generate go types from json", "golang unmarshal json to struct"]
tool_tag: "json-to-go-struct"
related_tool: "json-to-go-struct"
related_tools: ["json-to-go-struct", "json-formatter", "json-to-typescript", "json-path-finder", "json-diff", "json-schema-generator"]
updated_at: "2026-10-24T15:08:00Z"
og_image: "/images/content/guides/json-to-go-struct-guide-cover-20261024.webp"
image_alt: "A curly-brace JSON card on the left feeds glowing lines through a cyan funnel into three stacked Go struct cards on the right, each with typed field rows, on a dark navy background."
---

To turn JSON into Go structs, paste a sample into the FindUtils [JSON to Go Struct](/developers/json-to-go-struct/) generator, set the root struct name, choose whether to add `json` tags and `omitempty`, and press **Generate Go Struct**. Each JSON key becomes an exported PascalCase field with a `json:"key"` tag, each nested object becomes its own struct type, and the result can be copied or downloaded as a `.go` file. The conversion runs in your browser.

A generator only sees the one sample you give it, so treat the output as a first draft. This guide shows what each option produces, how each JSON value is mapped to a Go type, and the cases to fix by hand before the struct goes into your code.

## How to Generate a Go Struct From JSON, Step by Step

1. **Open [JSON to Go Struct](/developers/json-to-go-struct/).** Press **Load Sample** if you want to see an example first.
2. **Paste your JSON** into the JSON Input box. A real API response is the best input. If it arrives minified, the [JSON Formatter](/developers/json-formatter/) makes it readable first.
3. **Set the Struct Name.** It names the top-level type (the default is `Root`). Type a valid Go name such as `User` or `OrderResponse`.
4. **Choose the options.** **JSON Tags** (on by default) adds a `json:"..."` tag to every field. **Omit Empty** adds `,omitempty` to every tag. **Inline Structs** writes nested objects inside their parent instead of as separate types.
5. **Press Generate Go Struct.** The Go code appears on the right. If the input is not valid JSON, you see "Invalid JSON format" instead.
6. **Copy or download.** **Copy** puts the code on your clipboard; **Download.go** saves it as a file named after the struct, such as `root.go`.
7. **Run `gofmt`** (or let your editor format on save). The generator separates the name, type and tag of each field with one space; `gofmt` aligns them into columns.

## What the Generator Produces, With Real Output

With the built-in sample and the default options (JSON Tags on, Omit Empty and Inline Structs off), the output is:

```go
type Address struct {
	Street string `json:"street"`
	City string `json:"city"`
	ZipCode string `json:"zip_code"`
}

type Root struct {
	Id int `json:"id"`
	Name string `json:"name"`
	Email string `json:"email"`
	Age int `json:"age"`
	IsActive bool `json:"is_active"`
	Balance float64 `json:"balance"`
	Tags []string `json:"tags"`
	Address Address `json:"address"`
}
```

The nested `address` object became its own `Address` type, and the key `zip_code` became the field `ZipCode` with the original key kept in the tag. The struct compiles as it is.

**Omit Empty** changes every tag to the form `json:"street,omitempty"`. It is all or nothing: the option cannot mark only some fields as optional, so remove `,omitempty` by hand from fields that must always be sent. What `omitempty` actually leaves out (`0`, `false`, `""`, a nil pointer, an empty slice) is explained in [Go omitempty vs omitzero](/blog/go-json-omitempty-vs-omitzero-zero-values-pointers-and-null/).

**Inline Structs** writes the nested type in place:

```go
type Root struct {
	A struct {
		B int `json:"b,omitempty"`
	} `json:"a,omitempty"`
}
```

(shown after `gofmt`; the generator leaves the inner lines unindented). Use it for a small object that appears in one place only. Separate named types are easier to reuse and to write tests for.

**Turning JSON Tags off** removes the tags. That works only when the Go field names match the JSON keys apart from letter case, because Go's decoder falls back to a case-insensitive match. A key like `zip_code` would no longer reach the field `ZipCode`.

## How JSON Values Become Go Types

| JSON value | Example | Go type in the output |
|------------|---------|-----------------------|
| String | `"Ada"` | `string` |
| Whole number | `42`, `-3` | `int` |
| Number with a fraction | `1500.5` | `float64` |
| `true` / `false` | `true` | `bool` |
| `null` | `null` | `interface{}` |
| Object | `{"city": "Izmir"}` | A new struct named after the key |
| Array | `["a", "b"]` | A slice of the first element's type, `[]string` |
| Empty array | `[]` | `[]interface{}` |

Each nested struct is named by converting its key to PascalCase, so the key `items` gives a type called `Items`. Rename it to the singular (`Item`) if you prefer.

## Five Things to Check Before You Use the Output

These are cases where one sample does not contain enough information. We ran each one through the generator; the results below are what it produces today.

### 1. Numbers that look whole

The type is chosen from the value in the sample. `"price": 10.0` is read as the number 10, so the field becomes `int`. If the API later sends `10.5`, Go's `json.Unmarshal` returns an error ("cannot unmarshal number 10.5 into Go struct field ... of type int"), and it rejects the literal `10.0` in the same way. Use `float64` for prices, rates and measurements, whatever the sample shows. Use `int64` for IDs and counters that can grow large.

### 2. null

A `null` in the sample becomes `interface{}`, because the generator cannot tell what the field holds when it has a value. Replace it with a pointer to the real type, such as `*string` for a middle name or `*time.Time` for a `deleted_at` date. A pointer is `nil` when the key is missing or `null`, and points to the value otherwise.

### 3. Arrays

Only the first element of an array is used. For `[1, "a"]` the field becomes `[]int`, and decoding the string fails. For an array of objects, fields that only appear in later elements are left out: with `[{"id": 1}, {"id": 2, "sku": "x"}]` the struct has `Id` but no `Sku`. Put the most complete element first, or add the missing fields by hand.

**A top-level array is not handled.** If the whole document is an array, such as `[{"id": 1}, {"id": 2}]`, the generator treats the positions `0` and `1` as keys and writes invalid Go. Paste a single element instead (`{"id": 1}`), generate the struct, and decode the document into a slice of it: `var items []Root`.

### 4. Keys that are not valid Go names

Only `-`, `_` and spaces are converted. Other keys are copied into the field name as they are, so `"2fa"`, `"@type"` and `"user.email"` give lines that do not compile. Keys that differ only by separator or case also collide: `"user-id"`, `"user_id"` and `"userId"` all become `UserId`, and Go reports the field as redeclared. Rename those fields by hand, and keep the original key in the tag, for example:

```go
TwoFactor bool   `json:"2fa"`
Type      string `json:"@type"`
```

Go style also writes initialisms in one case: `ID`, `URL` and `HTTP`, not `Id`, `Url` and `Http`. The generator writes `Id` and `Url`, so rename them to follow the Go code review conventions. The tag keeps the JSON key, so renaming the field does not change the JSON.

### 5. Two objects with the same key

Nested types are named after their key, and a later object with the same key replaces the earlier type. With `{"author": {"name": "a"}, "post": {"author": {"id": 1}}}` the output has one `Author` type with only `Id`, so the top-level author's `name` is lost. When the same key holds different shapes, rename one of the types (for example `PostAuthor`) and add the missing fields.

## Tips

- **Check the field paths first.** For a large response, the [JSON Path Finder](/developers/json-path-finder/) shows the path to every value, which helps you decide which parts you need structs for.
- **Compare two responses** in [JSON Diff](/developers/json-diff/) to find fields that appear only sometimes. Those are the fields that need a pointer or `omitempty`.
- **Need the same data in TypeScript?** The [JSON to TypeScript](/developers/json-to-typescript/) generator does the same job for the front end; see the [JSON to TypeScript guide](/guides/json-to-typescript-guide/).
- **Want a contract, not just a type?** The [JSON Schema Generator](/developers/json-schema-generator/) writes a schema you can validate responses against.
- **Decode strictly while you test.** A Go `json.Decoder` with `DisallowUnknownFields()` returns an error for keys your struct does not have, which shows what the sample missed.

## FAQ

### How do I convert JSON to a Go struct online?

Paste the JSON into [JSON to Go Struct](/developers/json-to-go-struct/), set the struct name and options, and press Generate Go Struct. Copy the result or download it as a `.go` file, then run `gofmt` on it.

### Does the generator use int or float64 for JSON numbers?

It looks at the sample value: whole numbers become `int`, numbers with a fraction become `float64`. Because `10.0` is read as a whole number, check money and measurement fields and change them to `float64` where needed.

### What happens to null values?

They become `interface{}`. Change the field to a pointer of the real type, such as `*string`, so that a missing or `null` value decodes to `nil`.

### Can I convert a JSON array?

Not as the top-level value. Paste one element of the array, generate the struct, and decode the full array into a slice of that struct, for example `var users []User`.

### Does Omit Empty make the field optional when decoding?

No. `omitempty` only affects encoding (writing JSON). When decoding, a missing key simply leaves the field at its zero value, with or without the option.

### Is my JSON uploaded?

No. On this page the conversion runs in your browser, and the JSON is not sent anywhere.

## Related Reading

- [Go omitempty vs omitzero: zero values, pointers and null in JSON](/blog/go-json-omitempty-vs-omitzero-zero-values-pointers-and-null/)
- [JSON to TypeScript guide](/guides/json-to-typescript-guide/)
- [JSON Schema validation explained](/guides/json-schema-validation-explained/)
- [jq Playground guide](/guides/jq-playground-guide/)
- [Why JSON to CSV to SQL loses data types](/blog/why-json-to-csv-to-sql-loses-data-types/)

## Sources

- [Go standard library: package encoding/json](https://pkg.go.dev/encoding/json)
- [The Go Blog: JSON and Go](https://go.dev/blog/json)
- [Go Wiki: Code Review Comments, Initialisms](https://go.dev/wiki/CodeReviewComments#initialisms)
- [The Go Programming Language Specification: Identifiers](https://go.dev/ref/spec#Identifiers)
- [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://datatracker.ietf.org/doc/html/rfc8259)
