liveBook · Manning

Json.Decoder

As explained in Learn Go with Pocket-Sized Projects

A JSON decoder is a stateful component that reads JSON input and populates Go values from it.

Use `json.Decoder` when JSON comes from an `io.Reader`, such as an open file. Create it with `json.NewDecoder(reader)`, then call `Decode` with a pointer to the Go value that should receive the data. Check the returned error before using that value. section 3.1.3 section 6.5.4

The destination must match the JSON shape. For a list of bookworms, use a `[]Bookworm`; give its struct fields `json` tags to map JSON names to Go names. Fields must be exported so the decoder can fill them. Passing `&bookworms` lets decoding update the variable rather than a copy. section 3.1.3

Listing 3.6 bookworm.go: loadBookworms() parses the JSON file
// loadBookworms reads the file and returns the list of bookworms, 
// and their beloved books, found therein.
func loadBookworms(filePath string) ([]Bookworm, error) {
    f, err := os.Open(filePath) #1
    if err != nil {
        return nil, err
    }
    defer f.Close() #2

    // Initialize the type in which the file will be decoded.
    var bookworms []Bookworm

    // Decode the file and store the content in the variable bookworms.
    err = json.NewDecoder(f).Decode(&bookworms) #3
    if err != nil {
        return nil, err
    }

    return bookworms, nil
}

A complete file-loading function opens and closes the file, decodes into a slice, and returns any decoding error. section 3.1.3

Choose the API by the input you already have: `json.Decoder` reads an `io.Reader`, while `json.Unmarshal` accepts a complete `[]byte`. A byte slice can also be wrapped in a reader for `NewDecoder`. The file-loading example does not demonstrate the more refined approach of explicitly streaming a large input. section 3.5 section 6.5.4 section 3.1.3

p := person{}
dec := json.NewDecoder(bytes.NewReader(data)) // Or use an io.Reader
err := dec.Decode(&p)
if err != nil {
    panic(err)
}

A byte slice wrapped with `bytes.NewReader` shows that `Decode` still takes a pointer, even when the original data is already in memory. section 6.5.4

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Works through destination types, tags, pointers, errors, and API choice; defers explicit large-input streaming.
Examples
Shows an open-file bookworm loader and a byte slice decoded through `bytes.NewReader`.
What it assumes
Assumes basic Go structures and functions while explaining why decoding needs exported fields and a pointer.
What you can do after
Apply it via `encoding/json` to decode reader-backed JSON into a tagged Go value and handle errors.
How it connects
Connects `io.Reader`, `json.Unmarshal`, struct tags, exported fields, slices, and pointers to JSON decoding.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.