带有Go中可选字段的JSON

本文的翻译是为“ Golang开发人员。专业”课程的未来学生特别准​​备的


选项是配置文件中存储的最常见的数据类型之一在本文中,我将介绍在JSON中存储选项并在Go中取消编组时要考虑的一些事项。

特别是,期权和任何其他数据之间最重要的区别是,期权通常是可选的我们的程序可以具有大量各种配置参数(选项),但是我们可能需要仅使用它们的有限子集来启动任何特定的调用,而其他所有参数都保留默认值。

基础知识-部分编组,省略和未知字段

让我们从基础开始。考虑以下结构,这是一个任意程序选项:

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