Go structs define typed data models in Golang. Learn how struct tags, encoding/json, omitempty, and pointers enable robust JSON serialization.
A Go Struct (structure) is a composite data type in the Go (Golang) programming language that bundles named fields together under a single cohesive type. Go structs serve as the primary building block for object-oriented modeling, domain entities, database records, and network payloads in Golang applications.
When exchanging data over REST APIs, microservices, or gRPC gateways, Go developers serialize and deserialize JSON using the standard library's encoding/json package. By decorating struct fields with struct tags (such as json:"field_name,omitempty"), Go maps untyped JSON keys directly into strongly typed struct fields at compile time and runtime via reflection.
Instantly convert any JSON payload into idiomatic Golang struct definitions with our JSON to Go Struct Converter or explore type generation for other ecosystems with JSON to C# Class, JSON to TypeScript, JSON to Rust, and JSON to Zod.
| Specification | Details |
|---|---|
| Language | Go (Golang 1.0+ through 1.24+) |
| Standard Library Package | encoding/json |
| Core Functions | json.Marshal(), json.Unmarshal(), json.NewDecoder(), json.NewEncoder() |
| Tag Syntax | `json:"key_name[,options]"` (e.g. `json:"user_id,omitempty"`) |
| Field Export Rule | Fields starting with capital letters (Name) are public/exported; lowercase (name) are unexported/ignored by encoding/json |
| Nullability Model | Pointer types (*string, *int64, *bool) represent optional or nullable fields; value types hold zero values |
| Initialism Convention | Acronyms must be consistently uppercase (e.g., UserID, APIURL, HTTPStatus, IPAddress) |
| Dynamic JSON Types | json.RawMessage (deferred decoding), any / interface{} (unstructured dynamic mapping) |
| Extension Interfaces | json.Marshaler (MarshalJSON() ([]byte, error)), json.Unmarshaler (UnmarshalJSON([]byte) error) |
Struct tags are string literals enclosed in backticks placed after field type definitions. The encoding/json package parses these tags at runtime to determine field mapping rules during marshaling and unmarshaling.
package main
import (
"time"
)
type UserProfile struct {
ID int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
IsAdmin bool `json:"is_admin"`
Bio *string `json:"bio,omitempty"`
CreatedAt time.Time `json:"created_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
Roles []string `json:"roles"`
}
| Option | Syntax | Purpose & Behavior |
|---|---|---|
| Custom Key Name | `json:"custom_name"` | Maps the struct field to "custom_name" in JSON instead of the Go field name. |
omitempty |
`json:"key,omitempty"` | Omits the field from serialized JSON output if the field holds its type's zero value ("", 0, false, nil). |
| Skip Field | `json:"-"` | Instructs encoding/json to completely ignore this field during both serialization and deserialization. |
| Literal Dash Key | `json:"-,"` | Serializes the field to a JSON key literally named "-". |
| String Conversion | `json:"id,string"` | Automatically unmarshals a JSON string containing numbers/booleans into a Go numeric/boolean type. |
package main
import (
"encoding/json"
"fmt"
"log"
)
type Order struct {
OrderID string `json:"order_id"`
TotalAmount float64 `json:"total_amount"`
Currency string `json:"currency"`
Customer Customer `json:"customer"`
Items []OrderItem `json:"items"`
}
type Customer struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type OrderItem struct {
SKU string `json:"sku"`
Quantity int `json:"quantity"`
UnitPrice float64 `json:"unit_price"`
}
func main() {
rawJSON := []byte(`{
"order_id": "ORD-98421",
"total_amount": 129.99,
"currency": "USD",
"customer": {
"id": 402,
"name": "Sarah Connor",
"email": "[email protected]"
},
"items": [
{"sku": "CPU-X1", "quantity": 1, "unit_price": 99.99},
{"sku": "CBL-USB", "quantity": 2, "unit_price": 15.00}
]
}`)
var order Order
if err := json.Unmarshal(rawJSON, &order); err != nil {
log.Fatalf("JSON unmarshal error: %v", err)
}
fmt.Printf("Order %s for %s: $%.2f (%d items)\n",
order.OrderID, order.Customer.Name, order.TotalAmount, len(order.Items))
}
package main
import (
"encoding/json"
"fmt"
)
type Settings struct {
// Value bool: cannot differentiate between omitted/null and explicit false
NotificationEnabled bool `json:"notifications_enabled"`
// Pointer *bool: nil means omitted/null; &true or &false means explicitly provided
MarketingOptIn *bool `json:"marketing_opt_in,omitempty"`
}
func main() {
payloadWithNull := []byte(`{"notifications_enabled": false, "marketing_opt_in": null}`)
var s Settings
_ = json.Unmarshal(payloadWithNull, &s)
if s.MarketingOptIn == nil {
fmt.Println("MarketingOptIn was omitted or explicitly set to null")
}
}
Go uses identifier capitalization to govern visibility across packages. Fields beginning with an uppercase letter (Username) are exported (public), allowing the external encoding/json package to access and mutate them via reflection. Fields starting with lowercase letters (username) are private to the declaring package and are silently ignored by json.Marshal and json.Unmarshal.
json.RawMessage and any (interface{})?any (or interface{}) unmarshals JSON dynamically into standard Go types (map[string]any, []any, float64, string, bool), which requires runtime type assertions. In contrast, json.RawMessage is a []byte slice that delays unmarshaling, storing the raw unprocessed JSON tokens. This allows you to inspect discriminator fields before unmarshaling into a concrete sub-struct.
omitempty omit false and 0 values?In Go, omitempty checks if a field contains the default zero value of its type (0 for numbers, "" for strings, false for booleans, nil for pointers/slices). If an active toggle has IsActive: false, omitempty will omit "is_active": false from the JSON output. To preserve explicit false or 0 values in JSON output, use pointer fields (*bool, *int) so that only nil triggers omission.
Instead of manually typing out nested structs, types, and tag annotations, paste your JSON API response or payload into our JSON to Go Struct Converter to instantly generate idiomatic Golang types with customizable pointer and omitempty options.
Free, browser-based utilities to test, generate, and inspect Go Structs & JSON Serialization in Golang payloads directly.
Convert JSON to Go structs with json tags and idiomatic naming.
Convert JSON to C# classes with System.Text.Json or Newtonsoft serialization.
Convert JSON to TypeScript interfaces or type aliases instantly.
Convert JSON into idiomatic Rust structs with Serde Serialize and Deserialize derive macros.
Convert JSON to Zod schema definitions with automatic TypeScript type inference.
Repair and fix malformed JSON data from AI outputs, API responses, and copy-paste.
Convert cURL commands to idiomatic code across 14 programming languages instantly.