๐Ÿ“‹JSON EncodingLESSON

JSON Encoding

encoding/json โ€” No Third Party Needed

Go's standard library includes a complete JSON implementation in the encoding/json package. You do not need any external dependency to marshal structs to JSON or unmarshal JSON into Go types.

Struct Tags

Struct tags are string literals in backticks that annotate fields with metadata. The encoding/json package reads the json key to control serialization:

The tag maps the exported Go field name to the lowercase JSON key. Without a tag, Go uses the field name as-is, so Name would appear as "Name" in JSON.

omitempty โ€” omits the field when its value is the zero value for its type (empty string, 0, false, nil):

"-" โ€” always excludes the field from JSON, even if it has a value:

Marshaling: Go โ†’ JSON

json.Marshal converts a Go value to a JSON byte slice:

For human-readable output, use json.MarshalIndent:

Unexported fields are silently omitted โ€” json.Marshal can only see exported (capitalized) fields.

Unmarshaling: JSON โ†’ Go

json.Unmarshal parses a JSON byte slice into a Go value. Pass a pointer so the function can populate the struct:

Unknown JSON fields are silently ignored by default โ€” the "extra" key in the JSON will not cause an error.

Nested Structs and Slices

Struct fields can themselves be structs or slices โ€” the JSON encoder handles nesting automatically:

Embedded Structs

When a struct is embedded (without a field name), its fields are promoted to the top-level JSON object:

Marshaling an Article produces {"created_at":...,"updated_at":...,"title":...} โ€” the Timestamps fields appear at the top level.

Streaming I/O with Encoder and Decoder

When reading from or writing to a network connection or file, avoid buffering the entire JSON in memory. Use json.NewEncoder and json.NewDecoder instead:

json.NewEncoder(w).Encode(v) is idiomatic in HTTP handlers that write JSON responses to http.ResponseWriter.

Dynamic JSON with map[string]any

When the JSON structure is unknown at compile time, unmarshal into map[string]any:

JSON numbers decode as float64 by default. Use json.Decoder with UseNumber() if you need to distinguish integers from floats.

Knowledge Check

What struct tag makes a JSON field optional (omitted when zero value)?

What happens to unexported struct fields during json.Marshal?

Which function is best for streaming JSON to an io.Writer?