JSON mit optionalen Feldern in Go

Die Übersetzung des Artikels wurde speziell für zukünftige Studenten des Kurses "Golang Developer. Professional" vorbereitet .


Eine der häufigsten Arten von Daten, die in Konfigurationsdateien gespeichert sind, sind Optionen . In diesem Artikel werde ich einige der Nuancen behandeln, die beim Speichern von Optionen in JSON und beim Aufheben der Bereitstellung in Go zu berücksichtigen sind.

Insbesondere ist der wichtigste Unterschied zwischen Optionen und anderen Daten, dass Optionen häufig optional sind . Unser Programm kann eine große Anzahl aller Arten von Konfigurationsparametern (Optionen) enthalten. Möglicherweise müssen wir jedoch einen bestimmten Aufruf mit nur einer begrenzten Teilmenge davon initiieren und die Standardwerte für alles andere beibehalten.

Grundlagen - Partielle Anmarshaling-, Omitempty- und unbekannte Felder

. , :

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, .

. :

  1. JSON- , , Go .

  2. 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 , (, , ). - . , , , .

.




All Articles