JSON to Go Struct - Generate Go Structs from JSON
Turn a JSON sample into Go struct types with json tags. Paste JSON or choose a .json file, adjust the options, then copy or download gofmt-formatted source. Your JSON stays in your browser.
- Free
- Runs in your browser
- No data upload
- gofmt layout
Only UTF-8 JSON files are supported. Files are read locally and never uploaded.
The root name is used for the top type. Nested type names come from their JSON keys.
Optional means the key is missing from some elements of a JSON array of objects.
Ready. No JSON leaves your browser.
Generated Go
Your JSON input is not changed. The structs describe the sample you provided, so review them against real responses before use.
How to convert JSON to Go
-
Add your JSON
Paste a JSON sample or select a .json file. The file is read locally in your browser.
-
Adjust the options
Set the root type name, choose int or int64, and decide how nullable fields and optional keys are rendered.
-
Copy or download
Click Generate Go, then copy the structs or save them as types.go. The layout matches gofmt output.
Paste JSON or choose a .json file, click Generate Go, then copy the output or download types.go. String values become string, integers become int64 or int, and every object becomes a named struct with a json tag per field.
When to use this JSON to Go converter
Start a Go client from a real API response instead of writing structs and tags by hand. Nested objects and arrays are followed automatically, so one sample produces the full set of types.
Keep a decoder in sync with a backend payload: paste a fresh response, generate the structs, and compare the fields with the ones you already use.
Document third-party JSON that your service consumes, so the field names and types are visible in code review.
Prototype a configuration file or a webhook body quickly, then refine the generated types by hand where the sample is incomplete.
How JSON values map to Go
| JSON value | Go | Notes |
|---|---|---|
| object | struct |
Nested objects become named struct types, or anonymous structs with the inline option. |
| string | string |
Quoted text, including timestamps and identifiers kept as text. |
| integer | int64 |
int with the option. A literal beyond the int64 range becomes float64 with a comment. |
| number with a fraction or exponent | float64 |
Detected from the source text, so 1.0 and 1e3 stay floats. |
| boolean | bool |
true or false. |
| null in every sample | any |
A comment marks the field as always null. |
| null in some samples | *T |
With pointers on (default). Turn them off and null decodes as the zero value. |
| array of one kind | []T |
All elements share a single element type. |
| array containing null | []*T |
Pointer elements keep null distinct from the zero value. |
| empty array | []any |
An empty array says nothing about the elements it would hold. |
| mixed array | []any |
Go has no union types, so mixed elements widen to any. |
| array of objects | []Item |
Elements are merged into one struct; a key missing from some elements gets omitempty. |
| root array or primitive | type Root []Item |
The root becomes a type alias for the whole value. |
| key a tag cannot hold | json:"-" |
Comma, quote, backslash, backtick, control character or empty key. The field is kept with a comment. |
Options explained
Root type name
The name of the top-level type. Characters that are not valid in a Go identifier are removed and the result is exported, so a name like "my response" becomes MyResponse.
int instead of int64
Integer fields use int when this is on. On a 64-bit platform int is 64 bits wide, but the choice changes the type your code depends on.
Pointers for nullable fields
A field that is null in some samples becomes *T, so null survives a decode and a re-encode. Slices are already nilable and are not wrapped.
omitempty mode
Optional only adds omitempty where a key is missing from some array elements. Every field adds it everywhere. Never leaves tags plain.
Inline nested structs
Nested objects are written as anonymous struct types instead of separate named types. Useful for one-off payloads, harder to reuse.
package main header
Adds the package clause so the output compiles on its own. Turn it off to paste the declarations into an existing file.
Limitations
The output describes one sample, not a runtime validator. Keep these limits in mind:
One sample. Anything the sample does not contain is invisible to the converter, and one observed shape is not proof of the next response.
Number kinds. Integer versus float is decided by how the value is written: 1 is int64 and 1.0 is float64. A value written without a fraction that your API treats as a float will be typed as an integer.
Large numbers. A number outside the int64 range becomes float64 and may lose precision. A number outside the float64 range, such as 1e400, becomes json.Number and the output then needs import "encoding/json".
Skipped keys. encoding/json cannot express a comma, quote, backslash, backtick, control character or the empty key in a tag name. Those fields are emitted with json:"-" and a comment, so their values are not decoded.
Merged objects. All elements of an array of objects are folded into one struct. If the same array carries two different shapes, the struct is wider than either one and the optional tags hide the difference.
No validation. The tool reports JSON syntax errors only. It does not check your data against a schema and it cannot confirm that a field type is correct for every response.
A selected file larger than 16,000,000 bytes is rejected before it is read. Input is limited to 2,000,000 characters, 512 levels of nesting and 5,000 generated struct types. Conversion runs on the browser main thread, so a very large sample may briefly block the page.
JSON to Go Struct FAQ
Does my JSON leave the browser?
No. Pasted JSON and selected files are converted locally in your browser. Loading the page still makes ordinary requests for the HTML, styles and scripts, but your data is not sent anywhere.
Is the generated code formatted like gofmt?
The output uses the same layout as gofmt: tabs for indentation, aligned field names and types, and one field per line. It is checked against gofmt during development, so pasting it into a formatted Go file does not reflow the structs.
Why does 1.0 become float64 while 1 becomes int64?
Numbers are read from the JSON text, not from JavaScript numbers. A literal written with a fraction or an exponent, such as 1.0 or 1e3, becomes float64; a plain integer literal becomes int64.
What happens to keys that cannot be used in a struct tag?
encoding/json does not allow a comma, quote, backslash, backtick or control character in a tag name, and the empty key cannot be matched either. Such a field is emitted with the json:"-" tag and a comment, so its value is skipped when decoding.
Why is a field typed any?
A field becomes any when every sample value is null, or when the sample mixes value kinds such as a number and a string. A comment above the field explains which case applied.
Can I change the root type name and the options?
Yes. Set the root type name, choose int or int64, decide whether nullable fields use pointers, and pick the omitempty mode before generating. Type names for nested objects come from their JSON keys.