1. Struct Tags & Field Name Mapping
In Go, struct fields MUST begin with a capital letter to be exported and accessible to the `encoding/json` package. Use struct tags (`json:"key_name"`) to specify exact JSON key names.
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int64 `json:"user_id"`
Username string `json:"username"`
Email string `json:"email,omitempty"` // Omit if empty string
IsActive bool `json:"is_active"`
SecretKey string `json:"-"` // Ignore field completely
}
func main() {
u := User{ID: 101, Username: "gopher", IsActive: true}
// Marshal struct to formatted JSON bytes
data, _ := json.MarshalIndent(u, "", " ")
fmt.Println(string(data))
}2. Unmarshaling JSON Bytes into Go Structs (`json.Unmarshal`)
To decode a JSON byte slice into a Go struct, pass a pointer (`&struct`) to `json.Unmarshal()`. Always handle returned error values explicitly.
jsonBytes := []byte(`{"user_id": 202, "username": "alice_dev", "is_active": true}`)
var user User
err := json.Unmarshal(jsonBytes, &user)
if err != nil {
log.Fatalf("JSON Unmarshal Error: %v", err)
}
fmt.Printf("Parsed User ID: %d, Name: %s\n", user.ID, user.Username)3. Streaming Decoders (`json.NewDecoder`) for HTTP APIs
When handling incoming HTTP request bodies in Net/HTTP handlers or Gin frameworks, use `json.NewDecoder(r.Body).Decode(&dst)` to decode JSON directly from the request stream without allocating intermediate byte buffers.
Pro Tips
- Use `decoder.DisallowUnknownFields()` to reject HTTP requests containing unexpected client fields.
- Use `json.Encoder` when writing API responses directly to `http.ResponseWriter`.