【问题标题】:Parse yaml to struct with dynamic fields将 yaml 解析为具有动态字段的结构
【发布时间】:2017-12-20 13:10:27
【问题描述】:

我使用以下代码将 yaml 解析为可以正常工作的结构。 现在让我们假设我有一个像 install 这样的结构,我知道它有两个 const propertiesNameGroup 但是另外我们可以有额外的 key val properties 这可能会改变, 你可以获得任何关键的val属性(动态)

我应该如何定义这个结构?这个想法是读取yaml文件修改一些值并将其写回(具有与修改值完全相同的结构)到FS因此我不想错过一些需要修改的 yaml 文件中的动态字段

主包

import (
    "fmt"
    "log"

    "github.com/go-yaml/yaml"
)

type File struct {
    TypeVersion string `yaml:"_type-version"`
    Dependency []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Requires []Requires
}

type Install struct {
    Name  string
    Group string
   //Here any key value can be
}

type Requires struct {
    Name string
    Type string
}

var data = `
_type-version: "1.0.0"
dependency:
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
    requires:
      - name: db
      - type: mongo
      - name: rst
      - name: test
      - name: test2
`

func main() {
    f := File{}

    err := yaml.Unmarshal([]byte(data), &f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t:\n%v\n\n", f)

    d, err := yaml.Marshal(&f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t dump:\n%s\n\n", string(d))
}

示例 Install可以像上面也可以像这样

    install:
       - name: api
         group: test
         a1:test2
         b1:test2

还有

   install:
           - name: api
             group: test
             z10:123
             zzz:111

namegroup 之后还有更多字段

【问题讨论】:

  • 你看过viper吗?您可以使用viper.Get() 进行通用查找,然后键入断言返回到您需要的任何内容,而不是将您的 YAML 数据加载到结构中。如果您需要“动态”访问并且不想使用每个可能的键定义结构,您可能会发现 viper 更易于使用。
  • 地图?只是猜测......
  • @Volker - 谢谢,map[interface{}]interface{} 的文档中有选项,但不确定如何在我的上下文中使用它...

标签: go struct


【解决方案1】:

Map 而不是安装的结构将有助于解决问题。

import (
    "fmt"
    "log"

    "github.com/go-yaml/yaml"
)

type File struct {
    TypeVersion string `yaml:"_type-version"`
    Dependency  []Dependency
}

type Dependency struct {
    Name     string
    Type     string
    CWD      string
    Install  []Install
    Requires []Requires
}

type Install map[string]string

func (i Install) name() string {
    return i["name"]
}

func (i Install) group() string {
    return i["group"]
}

type Requires struct {
    Name string
    Type string
}

var data = `
_type-version: "1.0.0"
dependency:
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api
         group: test
    requires:
      - name: db
      - type: mongo
      - name: rst
      - name: test
      - name: test2
`

func main() {
    f := File{}

    err := yaml.Unmarshal([]byte(data), &f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t:\n%v\n\n", f)

    d, err := yaml.Marshal(&f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t dump:\n%s\n\n", string(d))
}

【讨论】:

  • 谢谢,但这不是我想要的,看到 namegroup 是某种 const 和 a1 b1 z10 是一些动态字段,可以有很多使用 diff 关键字段...你能用你的答案解释你将如何解析这些动态字段吗?
  • 安装只是一张地图。您可以通过地图进行范围(循环)或编写一个 get func,它接受一个键来查找地图。您可以通过这些函数轻松获取动态字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 2021-03-13
  • 2018-07-10
  • 2019-01-20
  • 2019-01-17
  • 1970-01-01
相关资源
最近更新 更多