Why Generate Go Structs from JSON?
Go is a statically typed language — you need a struct that matches your JSON before you can unmarshal (parse) it. Writing these structs by hand for large or nested API responses is tedious and error-prone.
The workflow is simple: paste the JSON response you receive from an API, get the Go struct back, paste it into your code, and start using it immediately.
Basic Example
JSON input:
{
"id": 1,
"name": "Ravi Kumar",
"email": "ravi@example.com",
"active": true
}Generated Go struct:
type Root struct {
Id int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Active bool `json:"active"`
}JSON Type → Go Type Mapping
| JSON type | Go type | Notes |
|---|---|---|
| string | string | Direct mapping |
| integer | int64 | Safe for all JSON integer sizes |
| float | float64 | IEEE 754 double precision |
| boolean | bool | true/false |
| null | interface{} | No native null type — use pointer for optionality |
| object | Named struct | Separate struct definition |
| array of objects | []StructName | Typed slice |
| array of strings | []string | Typed slice |
| empty array | []interface{} | No type info available |
Nested Objects
JSON:
{
"user": {
"name": "Priya",
"address": { "city": "Ahmedabad", "country": "IN" }
}
}Go:
type UserAddress struct {
City string `json:"city"`
Country string `json:"country"`
}
type User struct {
Name string `json:"name"`
Address UserAddress `json:"address"`
}
type Root struct {
User User `json:"user"`
}Using the Struct with encoding/json
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
resp, err := http.Get("https://api.example.com/users/1")
if err != nil { panic(err) }
defer resp.Body.Close()
var user Root
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
panic(err)
}
fmt.Println(user.Name)
}Handling Null and Optional Fields
The generator maps null to interface{}. For optional fields (may be present or null), use a pointer:
type User struct {
Name string `json:"name"`
MiddleName *string `json:"middle_name"` // nil if absent or null
Age *int64 `json:"age"` // nil if absent
}Pointers let Go distinguish between "field present but null" and "field absent."
Field Naming Conventions
Go exports fields with PascalCase names. The json tag preserves the original JSON key:
type Product struct {
ProductId int64 `json:"product_id"` // snake_case in JSON
DisplayName string `json:"displayName"` // camelCase in JSON
CreatedAt string `json:"created_at"`
}Without the json tag, encoding/json uses the exact Go field name, which is usually wrong for APIs.
Limitations of Generated Structs
Multiple JSON shapes: If the API returns different shapes for different status codes, the generator only sees one sample. Build a union type or use interface{} for polymorphic fields.
Date/time strings: JSON has no date type. The generator maps them to string. Change to time.Time and add the proper json unmarshaling tag if needed.
Very large integers: JavaScript's Number type loses precision for integers beyond 2^53. For safe handling in Go, use json.Number or string-typed IDs.
Use JSONKit's JSON to Go Struct tool to generate Go types from any JSON in seconds — paste, copy, done.