登录
首页 >  Golang >  Go问答

如何在 Golang 中使用动态键解析 YAML

来源:Golang技术栈

时间:2023-03-30 18:04:09 146浏览 收藏

各位小伙伴们,大家好呀!看看今天我又给各位带来了什么文章?本文标题《如何在 Golang 中使用动态键解析 YAML》,很明显是关于Golang的文章哈哈哈,其中内容主要会涉及到golang等等,如果能帮到你,觉得很不错的话,欢迎各位多多点评和分享!

问题内容

我正在尝试使用 Go 解析 YAML 文件。问题是 YAML 文件中的键可能并不总是相同的。这是为了进行 API 版本控制,以便用户可以定义他们支持的版本。例如 V1、V2、V3 等。它们不需要按顺序排列,可以省略它们不支持的版本,即 V0、V2、V5 等。

package main

import (
  "fmt"
  "gopkg.in/yaml.v2"
)

var data = `
---
development:
  skip-header-validation: true
  V1:
    current: "1.0.0"
    mime_types:
      - application/vnd.company.jk.identity+json;
      - application/vnd.company.jk.user+json;
      - application/vnd.company.jk.role+json;
      - application/vnd.company.jk.scope+json;
      - application/vnd.company.jk.test+json;
    skip-mime-type-validation: true
    skip-version-validation: true
  V2:
    current: "2.0.0"
    mime_types:
      - application/vnd.company.jk.identity+json;
      - application/vnd.company.jk.user+json;
      - application/vnd.company.jk.role+json;
      - application/vnd.company.jk.scope+json;
      - application/vnd.company.jk.test+json;

`

type MajorVersion struct {
  Current                 string    `yaml:"current"`
  MimeTypes               []string  `yaml:"mime_types"`
  SkipVersionValidation   bool      `yaml:"skip-version-validation"`
  SkipMimeTypeValidation  bool      `yaml:"skip-mime-type-validation"`
}

type Environment struct {
  SkipHeaderValidation  bool        `yaml:"skip-header-validation"`
  Version               map[string]MajorVersion
}

func main() {
  e := Environment{}

  yaml.Unmarshal([]byte(data), &e)
  fmt.Println(e)
}

我在[这里看到了一个类似的问题](https://stackoverflow.com/questions/18412126/golang-parse-a- json-with-dynamic-key)

这是顶层,我还没有完全弄清楚如何从结构内部做到这一点。

正确答案

首先,您试图将根解析为Environment,但它的实际类型是map[string]Environment. [Unmarshaler](https://github.com/go- yaml/yaml/blob/v2/yaml.go#L31)其次,如果你想保持这种类型结构,你将需要一个自定义。像这样的东西:

package main

import (
    "fmt"

    "gopkg.in/yaml.v2"
)

var data = `
---
development:
  skip-header-validation: true
  V1:
    current: "1.0.0"
    mime_types:
      - application/vnd.company.jk.identity+json;
      - application/vnd.company.jk.user+json;
      - application/vnd.company.jk.role+json;
      - application/vnd.company.jk.scope+json;
      - application/vnd.company.jk.test+json;
    skip-mime-type-validation: true
    skip-version-validation: true
  V2:
    current: "2.0.0"
    mime_types:
      - application/vnd.company.jk.identity+json;
      - application/vnd.company.jk.user+json;
      - application/vnd.company.jk.role+json;
      - application/vnd.company.jk.scope+json;
      - application/vnd.company.jk.test+json;

`

type MajorVersion struct {
    Current                string   `yaml:"current"`
    MimeTypes              []string `yaml:"mime_types"`
    SkipVersionValidation  bool     `yaml:"skip-version-validation"`
    SkipMimeTypeValidation bool     `yaml:"skip-mime-type-validation"`
}

type Environment struct {
    SkipHeaderValidation bool
    Versions             map[string]MajorVersion
}

func (e *Environment) UnmarshalYAML(unmarshal func(interface{}) error) error {
    var params struct {
        SkipHeaderValidation bool `yaml:"skip-header-validation"`
    }
    if err := unmarshal(&params); err != nil {
        return err
    }
    var versions map[string]MajorVersion
    if err := unmarshal(&versions); err != nil {
        // Here we expect an error because a boolean cannot be converted to a
        // a MajorVersion
        if _, ok := err.(*yaml.TypeError); !ok {
            return err
        }
    }
    e.SkipHeaderValidation = params.SkipHeaderValidation
    e.Versions = versions
    return nil
}

func main() {
    var e map[string]Environment
    if err := yaml.Unmarshal([]byte(data), &e); err != nil {
        fmt.Println(err.Error())
    }
    fmt.Printf("%#v\n", e)
}

输出(使用化妆后):

map[string]main.Environment{
    "development": {
        SkipHeaderValidation: true,
        Versions:             {
            "V2": {
                Current:                "2.0.0",
                MimeTypes:              {"application/vnd.company.jk.identity+json;", "application/vnd.company.jk.user+json;", "application/vnd.company.jk.role+json;", "application/vnd.company.jk.scope+json;", "application/vnd.company.jk.test+json;"},
                SkipVersionValidation:  false,
                SkipMimeTypeValidation: false,
            },
            "V1": {
                Current:                "1.0.0",
                MimeTypes:              {"application/vnd.company.jk.identity+json;", "application/vnd.company.jk.user+json;", "application/vnd.company.jk.role+json;", "application/vnd.company.jk.scope+json;", "application/vnd.company.jk.test+json;"},
                SkipVersionValidation:  true,
                SkipMimeTypeValidation: true,
            },
        },
    },
}

今天带大家了解了golang的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>