首页 > 解决方案 > 加载包含不同结构项目列表的 YAML 文件

问题描述

我有一个格式如下的 YAML:

actions:
  - type: one
    onekey: value
  - type: two
    twokey: value
    foo: bar

我想将它加载到 Go 结构中。我尝试使用mapstructurs它,DecodeHook但我无法让它工作。

这是我尝试过的:

type Actions struct {
    actions []Action
}

type Action interface {
}

type One struct {
    Onekey string
}

type Two struct {
    Twokey string
    Foo    string
}

var actions Actions

func Load() {
...
    config := &mapstructure.DecoderConfig{
        DecodeHook: func(sourceType, destType reflect.Type, raw interface{}) (interface{}, error) {
            if fmt.Sprintf("%s", destType) == "Action" {
                var result Action

                switch raw.(map[string]interface{})["type"] {
                case "one":
                    result = One{}
                case "two":
                    result = Two{}
                }
                mapstructure.Decode(raw, &result)
                return result, nil
            }
            return raw, nil
        },
        Result: &actions,
    }
...
}

这很丑陋,也不起作用。我得到:

panic: interface conversion: interface {} is map[interface {}]interface {}, not map[string]interface {}

首先有:

if fmt.Sprintf("%s", destType) == "Action"

这是可怕的,但我让这部分工作的唯一方法。

然后是读取列表项并通过键将其转换为正确的结构type。有没有办法使这项工作?

谢谢!

标签: goyaml

解决方案


最后我采用了这种方法:

    config := &mapstructure.DecoderConfig{
        DecodeHook: func(sourceType, destType reflect.Type, raw interface{}) (interface{}, error) {
            var result Action
            if fmt.Sprintf("%s", destType) == "Action" {
                rawMap := raw.(map[interface{}]interface{})
                switch rawMap["type"] {
                case "one":
                    result = One{}
                case "two":
                    result = Two{}
                }

                mapstructure.Decode(raw, &result)
                return result, nil
            }
            return raw, nil
        },
        Result: &actions,
    }

我只是从 Go 开始,所以可能有更好的方法,但这有点解决了我遇到的两个问题。

更正:我不得不恢复if fmt.Sprintf("%s", destType) == "Action"reflect.TypeOf(result) == nil


推荐阅读