#go #yaml
#Вперед #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 := amp;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, amp;result)
return result, nil
}
return raw, nil
},
Result: amp;actions,
}
...
}
Это некрасиво и тоже не работает. Я получаю:
panic: interface conversion: interface {} is map[interface {}]interface {}, not map[string]interface {}
Сначала есть:
if fmt.Sprintf("%s", destType) == "Action"
это отвратительно, но единственный способ заставить эту часть работать.
Затем нужно прочитать элемент списка и привести его к нужной структуре с помощью type
ключа. Есть ли способ заставить это работать?
Спасибо!
Ответ №1:
В итоге я выбрал этот подход:
config := amp;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, amp;result)
return result, nil
}
return raw, nil
},
Result: amp;actions,
}
Я только начинаю с Go, так что мог бы быть способ получше, но это как бы решает две проблемы, которые у меня были.
Поправка: мне пришлось вернуться к if fmt.Sprintf("%s", destType) == "Action"
, поскольку reflect.TypeOf(result) == nil
Ответ №2:
Взгляните на пакет viper:https://github.com/spf13/viper Это позволяет вам читать из файлов toml, json yaml и т. Д., А Затем вы можете передавать каждое значение конфигурации в свою структуру.
Комментарии:
1. Я не совсем понял, как viper поможет мне со списками, содержащими разные типы…