JSON to Go Converter
Generate Go structs from JSON data. Paste your JSON and configure options:
Generate Go Structs from JSON
This tool converts JSON data into Go struct definitions with proper json tags. It infers types automatically and handles nested objects by generating separate struct types.
Example Output
From this JSON:
{
"id": 1,
"user_name": "john",
"is_active": true
}The converter generates:
package main
type Root struct {
ID int `json:"id,omitempty"`
UserName string `json:"user_name,omitempty"`
IsActive bool `json:"is_active,omitempty"`
}Options Explained
omitempty
Adds ,omitempty to json tags. When marshaling to JSON, fields with zero values (empty string, 0, false) are omitted:
// With omitempty
type User struct {
Name string `json:"name,omitempty"`
}
// {} if Name is empty
// {"name":"John"} if Name has valuePointer types
Uses pointer types for nested structs and optional fields. Helpful for distinguishing between "not set" (nil) and "set to zero value":
type User struct {
Age *int `json:"age,omitempty"`
Profile *Profile `json:"profile,omitempty"`
}Type Mapping
| JSON | Go | Notes |
|---|---|---|
| string | string | |
| integer | int / int64 | int64 for large values |
| float | float64 | |
| boolean | bool | |
| null | interface or pointer | |
| array | []T | Type from first element |
| object | Nested struct |
Using Generated Structs
Unmarshal JSON
import "encoding/json"
jsonData := []byte(`{"id": 1, "user_name": "john"}`)
var user Root
err := json.Unmarshal(jsonData, &user)
if err != nil {
log.Fatal(err)
}
fmt.Println(user.UserName) // "john"Marshal to JSON
user := Root{
ID: 1,
UserName: "john",
IsActive: true,
}
jsonBytes, err := json.Marshal(user)
// {"id":1,"user_name":"john","is_active":true}With HTTP APIs
resp, err := http.Get("https://api.example.com/user")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var user Root
err = json.NewDecoder(resp.Body).Decode(&user)Go Naming Conventions
The converter follows Go conventions:
- Exported fields — PascalCase (capitalized) for JSON access
- JSON tags — Preserve original key names for serialization
- Struct names — PascalCase from JSON key names
Handling Edge Cases
Empty arrays
Empty arrays become []interface since the element type can't be inferred. Update manually to the correct type.
Mixed-type arrays
If an array contains different types, it becomes []interface. Consider restructuring your data or using custom unmarshal logic.
Null values
Null values become interface by default, or pointer types if that option is enabled.
Related Tools
- JSON Validator — Validate JSON before converting
- JSON to Java — Generate Java POJOs
- JSON to Python — Generate Python dataclasses
- JSON to TypeScript — Generate TS interfaces
- JSON Schema Generator — Create schema from data
Frequently Asked Questions
Should I use omitempty?
Use omitempty when you want to exclude zero-value fields from JSON output. Don't use it when zero values are meaningful (e.g., a counter that can be 0).
When should I use pointer types?
Use pointers when you need to distinguish between "field not set" (nil) and "field set to zero value" (0, "", false). Common for optional API fields.
How do I handle custom types?
The generated structs use basic types. For custom types (like time.Time for dates), manually update the struct and implement custom UnmarshalJSON if needed.
Common Mistakes & Pro Tips
- Struct tags are mandatory to map JSON keys — Go exports fields by capitalizing them (`UserName`), but `encoding/json` only matches keys case-insensitively, so a snake_case key like `user_name` needs an explicit tag: `UserName string \`json:"user_name"\``. Without the correct tag the field stays at its zero value after `Unmarshal`.
- Numbers default to float64, integers may need int64 — When unmarshalling into `interface{}`, every JSON number becomes `float64`, losing integer precision above 2^53. Into a typed struct you control the type: use `int64` for large IDs/timestamps and `float64` for decimals. The generator may guess `int` from a whole-number sample — widen to `int64` for anything that can exceed 32-bit on 32-bit platforms.
- Zero values hide the difference between missing and present — An absent JSON key and a present `0`/`""`/`false` both leave a value-typed field at its zero value, so you can't tell them apart. Use a pointer (`*int`, `*string`) when you need to distinguish null/missing from a real zero — a `nil` pointer means the key was absent or null, while `&0` means it was explicitly 0.
- Empty and mixed arrays become []interface{} — An empty array `[]` gives no element type, so it's emitted as `[]interface{}`; a heterogeneous array does the same. Replace `[]interface{}` with the concrete element type (e.g. `[]Item`) once you know the schema, since `interface{}` forces type assertions everywhere.
- Add omitempty and handle dates yourself — `omitempty` in a tag (`json:"bio,omitempty"`) only affects marshalling — it omits zero-valued fields from output; it has no effect on decoding. Date strings remain `string` because there's no automatic time parsing; to get `time.Time` keep the field as `time.Time` (it parses RFC 3339) or unmarshal as `string` and convert.
Frequently Asked Questions
How do I handle optional or nullable fields?
Use a pointer type (`*string`, `*int`) so a JSON `null` or missing key becomes a `nil` pointer instead of a zero value — that's the only way to distinguish "absent" from "explicitly zero" with `encoding/json`. Alternatively, `sql.NullString`/`sql.NullInt64` or generics-based `Option` types work but are more verbose. Add `,omitempty` to the tag if you also want to omit nil fields when marshalling.
Why do I need json tags at all?
Go field names must be exported (capitalized) to be (un)marshalled, but exported names like `UserName` don't match lowercase or snake_case JSON keys. The `json:"..."` struct tag tells `encoding/json` exactly which key maps to the field. Without it, only case-insensitive exact matches work, so `user_name` would silently never populate `UserName`.
Should number fields be int, int64, or float64?
Use `int64` for identifiers, counts, and millisecond timestamps that can exceed 2^31; `int` is platform-dependent (32 or 64 bit). Use `float64` only for genuinely fractional values, and be aware JSON has no integer/float distinction in the wire format. For exact decimals (money) decode into a string or use a decimal library, since float64 can't represent values like 0.1 exactly.
How does the generator handle nested objects and arrays of objects?
Each distinct nested object shape becomes its own named struct, and `[{...}, {...}]` becomes `[]ThatStruct`. Anonymous inline structs are also possible but named structs are more reusable. If two nested objects have the same shape, you may want to deduplicate them into one shared struct by hand.
What happens to JSON keys that aren't valid Go identifiers?
The exported field name is sanitized (hyphens removed, segments capitalized), and the original key is preserved in the `json` tag. For example `"created-at"` becomes `CreatedAt string \`json:"created-at"\``. The tag is what actually binds during (un)marshalling, so the field name can be whatever is idiomatic.
Is my data uploaded anywhere?
No. The struct generation runs locally in your browser via JavaScript, so your JSON is never sent to any server. It's safe to paste internal payloads, and it works even with your network disconnected.