JSON to Go Struct
Generate Go structs from JSON
JSON Input
Go Output
What is JSON to Go Conversion?
JSON to Go conversion turns raw JSON data into Go type definitions that work with the encoding/json package in Go's standard library. Go is statically typed, so every JSON field needs a corresponding struct field with the correct type and a struct tag that tells the serializer which JSON key to map. Writing these definitions by hand for large or deeply nested API responses is slow and easy to get wrong.
The encoding/json package, defined in the Go specification since Go 1.0, uses reflection to match JSON keys to exported struct fields. The matching is case-insensitive by default, but explicit json struct tags are the standard practice because they remove ambiguity and let you use Go's PascalCase convention while the JSON stays in camelCase or snake_case. A converter automates this: it reads your JSON, infers Go types from the values, and outputs struct definitions with the correct tags.
Go's type system maps cleanly to JSON. Strings become string, booleans become bool, integers become int, and floating-point numbers become float64. Nested JSON objects become separate named structs, and arrays become slices. The one gap is null: Go has no universal nullable type, so null values typically become pointer types (*string, *int) or interface{}. A generator handles all of this in milliseconds.
Why Use a JSON to Go Converter?
Defining Go structs from JSON by hand means counting braces, guessing types, and rewriting tags every time the API changes. A converter removes that friction.
JSON to Go Use Cases
JSON to Go Type Mapping
The encoding/json package follows specific rules when mapping JSON values to Go types. The table below shows the default mapping and common alternatives. The "Default" column is what most generators produce. The "Alternative" column shows types you might choose based on your requirements, such as int64 for large IDs or pointer types for nullable fields.
| JSON Type | Example | Default | Alternative |
|---|---|---|---|
| string | "hello" | string | string |
| number (integer) | 42 | int | int64 |
| number (float) | 3.14 | float64 | float64 |
| boolean | true | bool | bool |
| null | null | interface{} | *string / *int |
| object | {"k": "v"} | struct | struct |
| array of strings | ["a", "b"] | []string | []string |
| array of objects | [{"id": 1}] | []Item | []Item |
| mixed array | [1, "a"] | []interface{} | []interface{} |
Go JSON Struct Tag Reference
Struct tags control how encoding/json serializes and deserializes fields. The json tag is by far the most common, but you can combine it with other tags (db, yaml, xml) on the same field. The tag syntax is a backtick-delimited string after the field type. Here are the json tag options that encoding/json supports.
| Tag | Behavior | Use Case |
|---|---|---|
| json:"name" | Maps struct field to JSON key "name" | Always generated |
| json:"name,omitempty" | Omits field from output if zero value | Optional fields |
| json:"-" | Field is never serialized or deserialized | Internal fields |
| json:"name,string" | Encodes int/bool as JSON string | String-encoded numbers |
json.Unmarshal vs json.NewDecoder
Go provides two ways to decode JSON: json.Unmarshal for byte slices and json.NewDecoder for io.Reader streams. Both use the same struct tag rules, but they differ in when to use them.
Code Examples
These examples show how to use Go structs generated from JSON in real programs, plus how to generate them from other languages. The Go examples use encoding/json from the standard library.
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
IsActive bool `json:"is_active"`
Tags []string `json:"tags"`
}
func main() {
data := []byte(`{"id":1,"name":"Alice","email":"alice@example.com","is_active":true,"tags":["admin","editor"]}`)
var user User
if err := json.Unmarshal(data, &user); err != nil {
panic(err)
}
fmt.Println(user.Name) // β Alice
fmt.Println(user.Tags) // β [admin editor]
}// JSON response from API β this is the shape you'd convert to Go:
const res = await fetch("https://api.example.com/users/1");
const user = await res.json();
// user β { "id": 1, "name": "Alice", "email": "alice@example.com" }
// Equivalent Go struct:
// type User struct {
// ID int `json:"id"`
// Name string `json:"name"`
// Email string `json:"email"`
// }import json
def json_to_go(data: dict, name: str = "Root") -> str:
lines = [f"type {name} struct {{"]
type_map = {str: "string", int: "int", float: "float64", bool: "bool"}
for key, value in data.items():
go_type = type_map.get(type(value), "interface{}")
field = key.title().replace("_", "") # snake_case β PascalCase
lines.append(f'\t{field} {go_type} `json:"{key}"`')
lines.append("}")
return "\n".join(lines)
data = json.loads('{"user_name": "Alice", "age": 30, "verified": true}')
print(json_to_go(data))
# type Root struct {
# UserName string `json:"user_name"`
# Age int `json:"age"`
# Verified bool `json:"verified"`
# }package main
import (
"encoding/json"
"fmt"
"strings"
)
type Event struct {
Type string `json:"type"`
Payload string `json:"payload"`
}
func main() {
stream := strings.NewReader(`{"type":"click","payload":"btn-1"}
{"type":"scroll","payload":"page-2"}`)
dec := json.NewDecoder(stream)
for dec.More() {
var ev Event
if err := dec.Decode(&ev); err != nil {
break
}
fmt.Printf("%s: %s\n", ev.Type, ev.Payload)
}
// β click: btn-1
// β scroll: page-2
}