intermediate Step 12 of 15

Working with JSON

Go Programming

Working with JSON

JSON is the standard data format for web APIs, and Go's encoding/json package provides powerful tools for marshaling (Go to JSON) and unmarshaling (JSON to Go). Struct tags control how fields are serialized, and Go's strict typing ensures that your JSON handling is safe and predictable. Understanding JSON handling is critical for building APIs, consuming third-party services, and working with configuration files.

JSON Marshaling and Unmarshaling

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID        int      `json:"id"`
    Name      string   `json:"name"`
    Email     string   `json:"email"`
    Age       int      `json:"age,omitempty"`
    Password  string   `json:"-"`  // Never include in JSON
    Roles     []string `json:"roles"`
}

func main() {
    // Marshal (Go struct -> JSON)
    user := User{
        ID:       1,
        Name:     "Alice",
        Email:    "alice@example.com",
        Password: "secret",
        Roles:    []string{"admin", "user"},
    }

    jsonBytes, err := json.MarshalIndent(user, "", "  ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(jsonBytes))
    // {"id":1,"name":"Alice","email":"alice@example.com","roles":["admin","user"]}
    // Note: Password is excluded, Age is omitted (zero value + omitempty)

    // Unmarshal (JSON -> Go struct)
    jsonStr := `{"id":2,"name":"Bob","email":"bob@example.com","age":25}`
    var user2 User
    err = json.Unmarshal([]byte(jsonStr), &user2)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", user2)

    // Dynamic JSON with map
    var data map[string]interface{}
    json.Unmarshal([]byte(jsonStr), &data)
    fmt.Println(data["name"])  // "Bob"
}
Pro tip: Use struct tags to control JSON field names and behavior: json:"name" for renaming, json:",omitempty" to skip zero values, and json:"-" to exclude fields entirely. Always handle marshaling errors, even though they are rare with simple types.

Key Takeaways

  • Use json.Marshal()/json.Unmarshal() for JSON conversion with struct tags for field control.
  • json:",omitempty" excludes zero-value fields; json:"-" always excludes the field.
  • Use json.MarshalIndent() for human-readable JSON output.
  • Use json.NewDecoder() for streaming JSON from io.Reader (like HTTP request bodies).
  • Fields must be exported (uppercase) to be included in JSON marshaling.