将YAML解组为未知结构体

huangapple go评论88阅读模式
英文:

Unmarshal YAML into unknown struct

问题

抱歉,标题可能有些混乱,我在表达这个问题时遇到了困难。假设我有一个像这样的YAML配置文件:

animals:
  -
    type: whale
    options:
      color: blue
      name: Mr. Whale
    features:
      -
        type: musician
        options:
          instruments:
            - Guitar
            - Violin

这只是一个很牵强的例子,但与我实际工作的情况非常类似。

现在我有一些结构体来将这个配置解组为:

type Config struct {
  AnimalConfigs []*AnimalConfig `yaml:"animals"`
}

type AnimalConfig struct{
  Type string
  Options map[string]string // ????
  Features []*FeatureConfig
}

type FeatureConfig struct{
  Type string
  Options ????
}

问题在于动物类型(如鲸鱼等)和特征(如音乐家等)不能提前确定,它们可以作为单独的模块添加,并且每个模块都可以有自己的配置。假设有人在使用这个库时想要添加自己的动物。我不知道这个动物是什么,它的选项是什么,以及它的特征是什么。我也不知道特征的结构。我只知道它将有一个type属性和一个options属性。我希望开发人员能够添加自定义的动物和特征,而我的库只需执行类似于YourAnimal.Create(yourConfig)的操作。

我正在使用go-yaml库。正如你在AnimalConfig结构体中看到的,我最初的想法是将optionsfeatures设置为map[string]string,然后让自定义模块将该字符串解组为它们自己的结构体。但是,对于musician特征来说,这种方法行不通,因为instruments是一个列表,而不是一个字符串。谢谢!

英文:

Sorry for the confusing title, I'm having trouble wording this question. So lets say I have a YAML config file like this

animals:
  -
    type: whale
    options:
      color: blue
      name: Mr. Whale
    features:
       -
         type: musician
         options:
           instruments:
             - Guitar
             - Violin

Very contrived example, but it's directly analogous to what I'm really working with.

So now I have some structs to marshal this config into

type Config struct {
  AnimalConfigs []*AnimalConfig `yaml:"animals"`
}

type AnimalConfig struct{
  Type string
  Options map[string]string // ????
  Features []*FeatureConfig
}

type FeatureConfig struct{
  Type string
  Options ????
}

So the problem here is that the animal types (whale, etc..), and features (musician, etc...) are not determined ahead of time, they can be added on as separate modules and can each have their own configurations. So say someone is using this library and wants to add their own animal. I do not know what this animal is, what it's options will be, and what it's features will be. I also don't know the structure of the feature's. All I know is that it will have a type property, and an options property. I would like the developer to be able to add custom animals and features, and my library can just do something like YourAnimal.Create(yourConfig).

I'm using the go-yaml library. As you can see in the AnimalConfig struct, my initial idea was to have the options and features just be map[string]string, and then let the custom module unmarshal that string into their own struct, but that wouldn't work for example with the musician feature because instruments is a list, not a string. Thanks!

答案1

得分: 3

我认为你的问题大致是如何在不知道产生的结构的情况下解析YAML,是吗?如果是这样,我所做的是使用ghodss/yaml将YAML转换为JSON,然后使用标准的encoding/json进行解析。这样可以得到一个包含YAML文档中所有内容的struct,但你需要通过"类型切换"来处理它,并且键名可能事先不知道。

这里有一个示例:https://play.golang.org/p/8mcuot-lw0y

英文:

I think in general what you are asking is how to unmarshal YAML when you don't know the structure which will be produced, yes? If so, what I've done is use ghodss/yaml to convert YAML to JSON, then use the standard encoding/json to unmarshal. This gets you a struct with everything in the YAML doc, but you have to "type switch" your way through it, and key names, of course, may not be known a prioir.

Here's an example: https://play.golang.org/p/8mcuot-lw0y

答案2

得分: -1

你可以将配置文件的类型设置为map[string]interface{},然后让使用你的库的开发者将interface{}解码为所需的结构体。

示例:https://play.golang.org/p/RVqKP09KR8

英文:

You could make your config of type map[string]interface{} and let the developer using your library decode interface{} into required struct.
Example: https://play.golang.org/p/RVqKP09KR8

huangapple
  • 本文由 发表于 2017年1月21日 10:16:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/41775106.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定