gogolangjsontypes

JSON to Go Struct: Generate Go Types from API Responses

·7 min read

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:

json
{
  "id": 1,
  "name": "Ravi Kumar",
  "email": "ravi@example.com",
  "active": true
}

Generated Go struct:

go
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 typeGo typeNotes
stringstringDirect mapping
integerint64Safe for all JSON integer sizes
floatfloat64IEEE 754 double precision
booleanbooltrue/false
nullinterface{}No native null type — use pointer for optionality
objectNamed structSeparate struct definition
array of objects[]StructNameTyped slice
array of strings[]stringTyped slice
empty array[]interface{}No type info available

Nested Objects

JSON:

json
{
  "user": {
    "name": "Priya",
    "address": { "city": "Ahmedabad", "country": "IN" }
  }
}

Go:

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

go
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:

go
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:

go
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.

Try JSON to Go Struct

Generate Go structs with json tags from any JSON object automatically.