New blogMaking an AI Agent You Can Trust With Money

★ Go struct · from JSON

JSON to Go struct Converter

Go structs with the tags already written. Field names follow Go conventions (UserID, not UserId), optional keys get omitempty, nullable ones become pointers, and timestamps become time.Time.

  • Runs in your browser
  • No signup

Strictness

Your JSON

Go struct

3 types · 16 fields
import "time"

type Root struct {
	ID          int64     `json:"id"`
	Email       string    `json:"email"`
	DisplayName string    `json:"display-name"`
	CreatedAt   time.Time `json:"createdAt"`
	Plan        any       `json:"plan"`
	Tags        []string  `json:"tags"`
	Team        Team      `json:"team"`
	Invoices    []Invoice `json:"invoices"`
}

type Invoice struct {
	Number string     `json:"number"`
	Amount float64    `json:"amount"`
	Paid   bool       `json:"paid"`
	PaidAt *time.Time `json:"paidAt"`
	Note   string     `json:"note,omitempty"`
}

type Team struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	Website string `json:"website"`
}

Typing APIs by hand?

I set up end-to-end type safety (DB → API → UI) so this never happens again.

Fix my types
01

How the Go struct mapping works

Each JSON value is read, merged with every other sample of the same key, and then mapped to the closest Go struct type:

JSON to Go struct mapping
In your JSONGo struct
stringstring
ISO timestamptime.Time
integer / decimalint64 / float64
true / falsebool
null alongside a value*T (pointer)
key missing in some samples`json:"key,omitempty"`
array[]T
mixed values or always nullany
nested objectits own named struct
02

Worked example

A user record with a nested team, a list of invoices (one missing a note, one with a null payment date) and an awkward display-name key:

{
  "id": 1042,
  "email": "ada@example.com",
  "display-name": "Ada",
  "createdAt": "2026-11-07T09:30:00Z",
  "plan": null,
  "tags": ["beta", "founder"],
  "team": {
    "id": "7f3c9a2e-1b4d-4c8e-9f2a-6d5e4c3b2a19",
    "name": "Analytical Engines",
    "website": "https://example.com"
  },
  "invoices": [
    { "number": "INV-001", "amount": 49.5, "paid": true, "paidAt": "2026-10-01T00:00:00Z" },
    { "number": "INV-002", "amount": 49, "paid": false, "paidAt": null, "note": "Card declined" }
  ]
}

Becomes this Go struct, generated by the same engine that runs the converter above (3 types, 16 fields):

import "time"

type Root struct {
	ID          int64     `json:"id"`
	Email       string    `json:"email"`
	DisplayName string    `json:"display-name"`
	CreatedAt   time.Time `json:"createdAt"`
	Plan        any       `json:"plan"`
	Tags        []string  `json:"tags"`
	Team        Team      `json:"team"`
	Invoices    []Invoice `json:"invoices"`
}

type Invoice struct {
	Number string     `json:"number"`
	Amount float64    `json:"amount"`
	Paid   bool       `json:"paid"`
	PaidAt *time.Time `json:"paidAt"`
	Note   string     `json:"note,omitempty"`
}

type Team struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	Website string `json:"website"`
}
03

Go struct gotchas

Zero values hide missing keys

Without a pointer, a missing int decodes as 0 and you can't tell it from a real 0. Make a field a pointer when absent and zero mean different things.

omitempty only affects encoding

It drops zero values when marshalling. It doesn't make decoding stricter or tell you a key was missing.

int64 for every integer

JSON numbers have no size. int64 is the safe default; narrow to int32 or uint only when you know the range.

04

Questions developers actually ask

Why are IDs named ID, not Id?
Go style keeps initialisms upper-case: ID, URL, HTTP, UUID. The tool applies the common ones so golint stays quiet.
Do I need the import for time?
Only when a timestamp field exists. The generated code adds import "time" in that case; add it to your existing import block.
How do I reject unknown fields?
Use a json.Decoder and call DisallowUnknownFields() before Decode.
Is my JSON sent to a server?
No. Parsing and type generation run in your browser, so you can paste real API responses with tokens or customer data. Nothing leaves the tab.
How does it know a field is optional?
Paste an array of objects, or a response that contains one. Every element is read and merged: keys missing from some elements become optional, and keys that are sometimes null become nullable.
05

Other languages

06

More from the workbench

Fine print

Tools: on the house.
Engineer: by the hour.

A codebase that doesn't need this tool is the upgrade. I set up end-to-end type safety so your API, database and UI agree by construction.

I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.