Infrastructure Go daemon
SECTION 5.2

JSON Round-Tripping

1 · Before you read — commit to an answer
payload := map[string]any{
    "replicas":  3,
    "namespace": "production",
    "name":      "web-1",
}
body, _ := json.Marshal(payload)
fmt.Println(string(body))

Commit to the exact bytes — including the key order — before reading on.

That pretest hides a guarantee worth knowing: json.Marshal always emits map keys in sorted order, no matter how the literal was written. Insertion order is gone; alphabetical order is what hits the wire. That's what makes JSON output diffable in tests.

Decoding Response Bodies

2 · Worked example — read every step
// Option 1: json.NewDecoder (streaming, preferred for HTTP)
var pods []Pod
if err := json.NewDecoder(resp.Body).Decode(&pods); err != nil {
    return fmt.Errorf("decoding response: %w", err)
}

// Option 2: read all, then unmarshal (when you need the raw bytes too)
body, err := io.ReadAll(resp.Body)
if err != nil {
    return fmt.Errorf("reading body: %w", err)
}
var pods []Pod
if err := json.Unmarshal(body, &pods); err != nil {
    return fmt.Errorf("parsing JSON: %w", err)
}

Building Request Bodies

// POST with JSON body
payload := map[string]any{
    "name":      "web-1",
    "namespace": "production",
    "replicas":  3,
}
body, err := json.Marshal(payload)
if err != nil {
    return fmt.Errorf("encoding body: %w", err)
}

req, err := http.NewRequest("POST", url, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
3 · Fill the gaps
The outbound half again, from memory — data to wire bytes, wrapped for the request, plus the header APIs check.
payload := map[string]any{"name": "web-1", "replicas": 3}

body, err := json. if err != nil { return fmt.Errorf("encoding body: %w", err) }

req, err := http.NewRequest("POST", url, ) if err != nil { return fmt.Errorf("creating request: %w", err) } req.Header.Set(, "application/json")

4 · From scratch — this feeds your review queue