The translation of the article has been prepared especially for future students of the "Golang Developer. Professional" course .
One of the most common types of data stored in configuration files is options . In this article, I'll cover some of the nuances to consider when storing options in JSON and unmarshaling them in Go.
In particular, the most important difference between options and any other data is that options are often, pardon the pun ... optional . Our program can have a large number of various configuration parameters (options), but we may need to initiate any specific invocation with only a limited subset of them, leaving the default values ββfor everything else.
Basics - Partial Anmarshaling, Omitempty, and Unknown Fields
. , :
type Options struct {
Id string `json:"id,omitempty"`
Verbose bool `json:"verbose,omitempty"`
Level int `json:"level,omitempty"`
Power int `json:"power,omitempty"`
}
4 , .
, JSON- . :
{
"id": "foobar",
"verbose": false,
"level": 10,
"power": 221
}
, . json.Unmarshal
, .
. :
JSON- , , Go .
JSON- , . , .
(1) json
Go , JSON; Go. , JSON level
, Options Level
0. , .
(2) json
. , JSON:
{
"id": "foobar",
"bug": 42
}
json.Unmarshal
Options
, Id
"foobar"
, Level
Power
0, Verbose
false
. bug
.
, - . , json
, JSON- DisallowUnknownFields
:
dec := json.NewDecoder(bytes.NewReader(jsonText))
dec.DisallowUnknownFields()
var opts Options
if err := dec.Decode(&opts2); err != nil {
fmt.Println("Decode error:", err)
}
JSON .
, , Options
omitempty
, . , JSON. :
opts := Options{
Id: "baz",
Level: 0,
}
out, _ := json.MarshalIndent(opts, "", " ")
fmt.Println(string(out))
:
{
"id": "baz"
}
. , omitempty.
, JSON- Go. , , . , Power 10, 0? , JSON Β«powerΒ», Power
10, Unmarshal
.
- ! Power 10 , JSON 0! . , JSON 0?
, . , json.Unmarshal
:
func parseOptions(jsn []byte) Options {
opts := Options{
Verbose: false,
Level: 0,
Power: 10,
}
if err := json.Unmarshal(jsn, &opts); err != nil {
log.Fatal(err)
}
return opts
}
json.Unmarshal
Options
, parseOptions
.
UnmarshalJSON
Options
:
func (o *Options) UnmarshalJSON(text []byte) error {
type options Options
opts := options{
Power: 10,
}
if err := json.Unmarshal(text, &opts); err != nil {
return err
}
*o = Options(opts)
return nil
}
json.Unmarshal
Options
Power . options - UnmarshalJSON
.
, . -, . , , ; .
, . Options
, . :
type Region struct {
Name string `json:"name,omitempty"`
Power int `json:"power,omitempty"`
}
type Options struct {
Id string `json:"id,omitempty"`
Verbose bool `json:"verbose,omitempty"`
Level int `json:"level,omitempty"`
Power int `json:"power,omitempty"`
Regions []Region `json:"regions,omitempty"`
}
Power
Region
, Options
. Region. - UnmarshalJSON
.
, . -.
-
Options
:
type Options struct {
Id *string `json:"id,omitempty"`
Verbose *bool `json:"verbose,omitempty"`
Level *int `json:"level,omitempty"`
Power *int `json:"power,omitempty"`
}
, , . , JSON:
{
"id": "foobar",
"verbose": false,
"level": 10
}
, , "power". :
var opts Options
if err := json.Unmarshal(jsonText, &opts); err != nil {
log.Fatal(err)
}
, ( nil
), , ( ). , Options
:\
func parseOptions(jsn []byte) Options {
var opts Options
if err := json.Unmarshal(jsonText, &opts); err != nil {
log.Fatal(err)
}
if opts.Power == nil {
var v int = 10
opts.Power = &v
}
return opts
}
, opts.Power
; , Go , , int
. , , :
func Bool(v bool) *bool { return &v }
func Int(v int) *int { return &v }
func String(v string) *string { return &v }
// .. ...
, opts.Power = Int(10)
.
, , JSON. Options
, , nil
.
- Β« Β»? . , , , . Protobuf protobuf- proto2
, . !
, . , , Go , (, , ). - . , , , .