go - 自定义结构的 UnmarshalYAML 接口(interface)的实现

标签 go struct yaml unmarshalling

我有以下结构、接口(interface)和函数:

type FruitBasket struct {
    Capacity int `yaml:"capacity"`
    Fruits []Fruit
}

type Fruit interface {
    GetFruitName() string
}

type Apple struct {
    Name string `yaml:"name"`
}

func (apple *Apple) GetFruitName() string {
    return apple.Name
}

type tmpFruitBasket []map[string]yaml.Node

func (fruitBasket *FruitBasket) UnmarshalYAML(value *yaml.Node) error {
    var tmpFruitBasket tmpFruitBasket

    if err := value.Decode(&tmpFruitBasket); err != nil {
        return err
    }

    fruits := make([]Fruit, 0, len(tmpFruitBasket))

    for i := 0; i < len(tmpFruitBasket); i++ {
        for tag, node := range tmpFruitBasket[i] {
            switch tag {
            case "Apple":
                apple := &Apple{}
                if err := node.Decode(apple); err != nil {
                    return err
                }

                fruits = append(fruits, apple)
            default:
                return errors.New("Failed to interpret the fruit of type: \"" + tag + "\"")
            }
        }
    }

    fruitBasket.Fruits = fruits

    return nil
}

使用这段代码,我可以解析以下 yaml 文件:

FruitBasket:
  - Apple:
      name: "apple1"
  - Apple:
      name: "apple2"

主要功能如下:

func main() {
    data := []byte(`
FruitBasket:
  - Apple:
      name: "apple1"
  - Apple:
      name: "apple2"
`)

    fruitBasket := new(FruitBasket)

    err := yaml.Unmarshal(data, &fruitBasket)

    if err != nil {
        log.Fatalf("error: %v", err)
    }

    for i := 0; i < len(fruitBasket.Fruits); i++ {
        switch fruit := fruitBasket.Fruits[i].(type) {
        case *Apple:
            fmt.Println("The name of the apple is: " + fruit.GetFruitName())
        }
    }
}

但是,我无法解析以下 yaml 字符串:

FruitBasket:
  capacity: 2
  - Apple:
      name: "apple1"
  - Apple:
      name: "apple2"

使用此字符串,我收到以下错误:错误:yaml:未找到预期的 key

我必须如何调整 UnmarshalYAML 接口(interface)的实现,才能同时解析后面的字符串?

最佳答案

您的 YAML 无效。每个 YAML 值都是标量、序列或映射。

capacity: 处,YAML 处理器在看到第一个键时决定此级别包含一个映射。现在,在下一行,它看到 - Apple:,一个序列项。这在映射级别内无效;它需要下一个键,因此给你一个错误 did not find expected key

结构的修复看起来像这样:

FruitBasket:
  capacity: 2
  items:
  - Apple:
      name: "apple1"
  - Apple:
      name: "apple2"

请注意,序列项仍然出现在同一级别,但是由于 items: 没有内联值,因此项被解析为序列,该序列是键 的值项目。同一缩进级别的另一个键将结束序列。

然后您可以将其加载到如下类型中:

type tmpFruintBasket struct {
  Capacity int
  Items []map[string]yaml.Node
}

关于go - 自定义结构的 UnmarshalYAML 接口(interface)的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59860059/

相关文章:

go - 关于内置函数的golang实现在哪里

Golang 将环境变量编译成二进制

c - 使用灵活数组成员时正确的 malloc 大小

c - 结构输出显示错误

c# - 在 C# 中,结构真的不能为 null 吗?

amazon-web-services - 使用 SAM 模板创建 DynamoDB 表时出现错误

ruby-on-rails - YAML 配置文件 : Why 'example' instead of :example?

go - 最简单的 Golang CGI 表单示例

go - 循环中的 Println 和闭包输出不同的值

YAML 多行数组