{}JSONLint.app

JSON to Go Converter

Generate Go structs from JSON data. Paste your JSON and configure options:

Loading...
Loading...

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 value

Pointer 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

JSONGoNotes
stringstring
integerint / int64int64 for large values
floatfloat64
booleanbool
nullinterface or pointer
array[]TType from first element
objectNested 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

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 keysGo 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 int64When 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 presentAn 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.