草庐IT

Golang 嵌套 Yaml 值

coder 2023-06-26 原文

我正在尝试访问 Yaml 文件并获取单个值,但我正在努力使用 Struct 语法来实现这一点。下面的代码处理 Yaml,我可以打印完整的结构,但我如何访问单个 ecs.services.name 属性?

欢迎就如何处理此问题提出任何建议,因为我遇到过多个 Yaml 库,但无法让其中任何一个充分发挥作用。

测试.yaml:

ecs:
  services:
    - name: my-service
      taskDefinition: my-task-def
      desiredCount: 1

Yaml.go

package main

import (
    "fmt"
    "io/ioutil"
    "path/filepath"

    "gopkg.in/yaml.v2"
)

type Config struct {
    //Ecs []map[string]string this works for ecs with name
    Ecs struct {
        Services []struct {
            Name           string
            TaskDefinition string
            DesiredCount   int
        }
    }
    //Services []map[string][]string
}

func main() {
    filename, _ := filepath.Abs("test.yaml")

    yamlFile, err := ioutil.ReadFile(filename)
    check(err)

    var config Config

    err = yaml.Unmarshal(yamlFile, &config)
    check(err)

    fmt.Printf("Description: %#v\n", config.Ecs.Services)
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

输出

$ go run yaml.go
Description: []struct { Name string; TaskDefinition string; DesiredCount int }{struct { Name string; TaskDefinition string; DesiredCount int }{Name:"my-service", TaskDefinition:"", DesiredCount:0}}

最佳答案

我有一个类似的要求,我需要在 yaml 文件上执行嵌套检索。因为我没有发现开箱即用的解决方案,所以我不得不自己编写。

我有一个包含如下内容的 yaml 文件

"a": "Easy!"
"b":
  "c": "2"
  "d": ["3", "4"]
"e":
  "f": {"g":"hi","h":"6"}

我想从这个结构中访问和打印嵌套值,输出应该如下所示

--- yaml->a: Easy!
--- yaml->b->c: 2
--- yaml->b->x: None  //not existing in the yaml
--- yaml->y->w: None  //not existing in the yaml
--- yaml->b->d[0]: 3   //accessing value from a list
--- yaml->e->f->g: hi 

我也不想定义一个结构来保存解析后的 yaml。 golang 中最通用的结构是 interface{}。最适合解码 yaml 的结构是 map[interface{}]interface{} .对于来自 Java 的人来说,这类似于 Map<Object,Object> .数据解码后,我必须编写一个函数,该函数可以使用嵌套键遍历结构并返回值。

下面是实现它的代码。开启注释执行,就知道代码是如何遍历嵌套结构,最终取值的。尽管此示例假定 yaml 中的所有值都是字符串,但也可以将其扩展为数字键和值。

package main

import (
    "fmt"
    "gopkg.in/yaml.v2"
    "io/ioutil"
    "reflect"
)

func main() {

    testFile := "test.yaml"
    testYaml, rerr := ioutil.ReadFile(testFile)
    if rerr != nil {
        fmt.Errorf("error reading yaml file: %v", rerr)
    }

    m := make(map[interface{}]interface{})
    if uerr := yaml.Unmarshal([]byte(testYaml), &m); uerr != nil {
        fmt.Errorf("error parsing yaml file: %v", uerr)
    }

    fmt.Printf("--- yaml->a: %v\n\n", getValue(m, []string{"a"}, -1))         //single value in a map
    fmt.Printf("--- yaml->b->c: %v\n\n", getValue(m, []string{"b", "c"}, -1)) //single value in a nested map
    fmt.Printf("--- yaml->b->x: %v\n\n", getValue(m, []string{"b", "x"}, -1)) //value for a non existent nest key
    fmt.Printf("--- yaml->y->w: %v\n\n", getValue(m, []string{"y", "w"}, -1)) //value for a non existent nest key
    fmt.Printf("--- yaml->b->d[0]: %v\n\n", getValue(m, []string{"b", "d"}, 0))
    fmt.Printf("--- yaml->e->f->g: %v\n\n", getValue(m, []string{"e", "f", "g"}, -1))
}

func getValue(obj map[interface{}]interface{}, keys []string, indexOfElementInArray int) string {

    //fmt.Printf("--- Root object:\n%v\n\n", obj)
    value := "None"
    queryObj := obj
    for i := range keys {
        if queryObj == nil {
            break
        }
        if i == len(keys)-1 {
            break
        }
        key := keys[i]
        //fmt.Printf("--- querying for sub object keyed by %v\n", key)
        if queryObj[key] != nil {
            queryObj = queryObj[key].(map[interface{}]interface{})
            //fmt.Printf("--- Sub object keyed by %v :\n%v\n\n", key, queryObj)
        } else {
            //fmt.Printf("--- No sub object keyed by %v :\n%v\n\n", key)
            break
        }
    }
    if queryObj != nil {
        lastKey := keys[len(keys)-1]
        //fmt.Printf("--- querying for value keyed by %v\n", lastKey)

        if queryObj[lastKey] != nil {
            objType := reflect.TypeOf(queryObj[lastKey])
            //fmt.Printf("Type of value %v\n", objType)
            if objType.String() == "[]interface {}" {
                //fmt.Printf("Object is a array %v\n", objType)
                tempArr := queryObj[lastKey].([]interface{})
                //fmt.Printf("Length of array is %v\n", len(tempArr))
                if indexOfElementInArray >= 0 && indexOfElementInArray < len(tempArr) {
                    value = queryObj[lastKey].([]interface{})[indexOfElementInArray].(string)
                }
            } else {
                value = queryObj[lastKey].(string)
            }
        }
    }

    return value
}

关于Golang 嵌套 Yaml 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38310894/

有关Golang 嵌套 Yaml 值的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  3. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

  4. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

  7. ruby-on-rails - 使用回形针的嵌套形式 - 2

    我有一个名为posts的模型,它有很多附件。附件模型使用回形针。我制作了一个用于创建附件的独立模型,效果很好,这是此处说明的View(https://github.com/thoughtbot/paperclip):@attachment,:html=>{:multipart=>true}do|form|%>posts中的嵌套表单如下所示:prohibitedthispostfrombeingsaved:@attachment,:html=>{:multipart=>true}do|at_form|%>附件记录已创建,但它是空的。文件未上传。同时,帖子已成功创建...有什么想法吗?

  8. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  9. python - 是否可以使用 Ruby 或 Python 禁用 anchor /引用来发出有效的 YAML? - 2

    是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案

  10. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

随机推荐