Golang / GoLang Production Patterns and Web Standards Interview Questions
How do you encode and decode JSON in Go and what are the common pitfalls?
Go's encoding/json package provides json.Marshal/json.Unmarshal for byte slices and json.NewEncoder/json.NewDecoder for streams. The stream-based API is preferred for HTTP handlers since it avoids loading the full body into memory.
// Struct tags control JSON field names and omission type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` Password string `json:"-"` // always omit CreatedAt time.Time `json:"created_at"` Bio *string `json:"bio,omitempty"` // omit if nil Score int `json:"score,omitempty"` // omit if zero } // Decoding HTTP request body (preferred: streaming) func createUserHandler(w http.ResponseWriter, r *http.Request) { var user User dec := json.NewDecoder(r.Body) dec.DisallowUnknownFields() // reject unexpected JSON keys if err := dec.Decode(&user); err != nil { http.Error(w, fmt.Sprintf("invalid JSON: %v", err), http.StatusBadRequest) return } // ... process user ... w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(user) } // Common pitfalls: // 1. Unexported fields are silently ignored type Hidden struct { public string; private string } // private won't encode // 2. json.Number for large integers (avoid float64 precision loss) var data map[string]any dec := json.NewDecoder(r.Body) dec.UseNumber() // numbers decoded as json.Number, not float64 dec.Decode(&data) n, _ := data["id"].(json.Number).Int64() // 3. Circular references cause Marshal to panic â avoid // 4. Set Content-Type BEFORE WriteHeader w.Header().Set("Content-Type", "application/json") // must come first w.WriteHeader(http.StatusOK) // locks headers
More Related questions...