Go’s encoding/json package converts JSON bytes into Go values and Go values back into JSON. It is useful when a CLI needs to read a configuration file, check its structure, or produce structured output. Define a Go struct for the data, then use json.Unmarshal with the input bytes and a pointer to that struct. section 10.5.1 section 10.10
For a server configuration struct:
- Export fields so encoding/json can access them. Use tags such as `json:"port"` to map JSON keys to Go field names. section 10.5.1
- Use `json:"host,omitempty"` to omit an empty host when marshaling, or `json:"-"` to exclude a field. section 10.5.1
- Check errors returned by json.Unmarshal rather than treating unparsed input as a valid configuration. section 10.5.1
Parse a configuration
A JSON configuration with `name`, `version`, `debug`, `port`, and `host` maps to a `Config` struct with corresponding string, bool, and int fields. Pass its raw bytes and `&config` to `json.Unmarshal`; a type mismatch can then be reported before the configuration is used. section 10.5.1
// UnmarshalJSON validates the Host field to ensure it is a valid URL
func (c *Config) UnmarshalJSON(b []byte) error {
temp := struct { #1
Name string `json:"name"`
Version string `json:"version"`
Debug bool `json:"debug"`
Port int `json:"port"`
Host string `json:"host"`
}{}
if err := json.Unmarshal(b, &temp); err != nil { #2
return err
}
// Validate the Host field
if _, err := url.ParseRequestURI(temp.Host); err != nil { #3
return fmt.Errorf("invalid Host URL: %v", err)
}
*c = Config(temp) #4
return nil
}
A custom `UnmarshalJSON` method first decodes into a temporary struct, then validates the host before assigning the result. The temporary struct keeps the method from calling itself during decoding. section 10.5.1
func (c Config) MarshalJSON() ([]byte, error) {
// Use an anonymous struct to avoid recursion
temp := &struct {
Name string `json:"name"`
Version string `json:"version"`
Debug bool `json:"debug"`
Port int `json:"port"`
Host string `json:"host"`
}{
Name: c.Name,
Version: c.Version,
Debug: c.Debug,
Port: c.Port,
Host: "[REDACTED]", // Redact the host value
}
return json.Marshal(temp)
}
A custom `MarshalJSON` method builds a temporary value with a redacted host and passes it to `json.Marshal`, giving the output different contents from the stored configuration. section 10.5.1

