Practical guide

Generate Go structs from JSON

Go developers often want one thing from JSON generation: clean structs with the right field names and json tags. JSON All-in-One can infer Go structs from local JSON and give you a starting point for encoding/json work.

Review the generated structs alongside your decoder. Numeric types, nulls, date/time values, and mixed-value fields may need explicit handling before the data is ready for your application.

Use events that expose tags and pointers

This illustrative event response uses snake_case keys, nested objects, arrays, nulls, and a large integer. It is shaped to explain exported field names, JSON tags, optional nested structs, and integer policy.

For Go, include at least two records if the API returns arrays. A field that is null or absent in one record should be reviewed before you rely on a non-pointer generated field.

Illustrative root-array event JSONjson
[
  {
    "event_id": "evt_1001",
    "sequence": 9007199254740993,
    "kind": "deploy.started",
    "received_at": "2026-09-04T07:12:00Z",
    "actor": { "user_id": 10, "display_name": "Rae" },
    "labels": ["prod", "manual"]
  },
  {
    "event_id": "evt_1002",
    "sequence": 9007199254740994,
    "kind": "deploy.finished",
    "received_at": "2026-09-04T07:14:30Z",
    "actor": null,
    "labels": []
  }
]

Review structs and JSON tags

Generated Go structs should use exported field names so other packages can read them, while preserving original JSON keys in tags such as json:"event_id". That is the main value of a JSON-to-Go struct workflow: the code becomes idiomatic without losing the wire format.

After generation, check the top of each Go file before compiling. If a single-file output places an import below a type declaration, move the import block to the top of the file or switch to the multi-file output and compile again.

Illustrative Go structs for the root-array itemsgo
package events

type GeneratedRootItemActor struct {
    DisplayName string `json:"display_name"`
    UserId      int64  `json:"user_id"`
}

type GeneratedRootItem struct {
    Actor      *GeneratedRootItemActor `json:"actor"`
    EventId    string                  `json:"event_id"`
    Kind       string                  `json:"kind"`
    Labels     []string                `json:"labels"`
    ReceivedAt string                  `json:"received_at"`
    Sequence   int64                   `json:"sequence"`
}

type GeneratedRoot = []GeneratedRootItem

Verify decoding, not just syntax

Decode the sample with encoding/json and check the resulting field values. This catches mismatched tags, unexpected nulls, and numeric types that cannot hold the input.

If you choose native numbers, know why. If the JSON contains identifiers beyond JavaScript-safe range but within Go int64, decoding may still be fine for Go, while downstream JavaScript or spreadsheets could be unsafe. If you choose *big.Int or *big.Float, verify the decoder behavior separately.

Handwritten Go decode check for the root arraygo
var events GeneratedRoot
if err := json.Unmarshal([]byte(input), &events); err != nil {
    log.Fatal(err)
}

for _, event := range events {
    fmt.Println(event.EventId, event.Actor != nil)
}

Go policy choices

Go supports native or string date/time, native int64, *big.Int, or string integer policy, native float64 or *big.Float decimal policy, and native any or string for unknown JSON values. Those choices affect imports and decoding expectations.

Use time.Time only when the generated output and parsing format match the actual JSON. A timestamp string in JSON is not magically a time.Time unless the decoder can parse it in the expected format.

Option areaGo choicesWhat to verify
PackageGo package identifierName compiles in a small module.
Null nested objectPointer or value shapeDecode fixture with null.
Integerint64, *big.Int, or stringImports and decoder behavior.
Date/timestring or time.TimeTimestamp parse expectations.

Workflow checklist

  1. Open a representative array or object in JSON All-in-One.
  2. Select Go and set the package identifier.
  3. Review generated names, tags, pointers, slices, and primitive policies.
  4. Prefer multi-file output if single-file output places imports below declarations.
  5. Run a decode check against the exact fixture before relying on the model.

Limitations to keep visible

Generated Go structs do not replace API contracts or validation. They also do not automatically choose business-safe numeric representations. If an API sometimes sends a number and sometimes a string, the model should be reviewed as a union or custom type problem rather than pasted blindly.

Do not turn this workflow into a benchmark claim. The job is model generation and integration review, not speed testing.

Struct tags and decode responsibilities

Generate Go structs from a 1,000-record telemetry response, inspect nullable pointers and numeric slices, then run gofmt and an encoding/json decode test against the same fixture.
Diagram showing generated Go structs between telemetry JSON and handwritten encoding/json application policy.
Architecture diagram separating generated structs, JSON tags, pointers, slices, and enum types from handwritten decoding policy, validation, unknown-field handling, and schema evolution.