JSON com campos opcionais em Go

A tradução do artigo foi preparada especialmente para futuros alunos do curso "Golang Developer. Professional" .


Um dos tipos mais comuns de dados armazenados em arquivos de configuração são opções . Neste artigo, falarei sobre algumas das nuances a serem consideradas ao armazenar opções em JSON e desempacotá-las no Go.

Em particular, a diferença mais importante entre opções e quaisquer outros dados é que as opções são frequentemente, com o perdão do trocadilho ... opcionais . Nosso programa pode ter um grande número de todos os tipos de parâmetros de configuração (opções), mas podemos precisar iniciar qualquer invocação específica com apenas um subconjunto limitado deles, deixando os valores padrão para todo o resto.

Básico - Campos Parciais Anmarshaling, Omitempty e Desconhecidos

. , :

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