首页 > 后端开发 > Golang > 将 YAML 解组为复杂对象,可以是结构体或字符串

将 YAML 解组为复杂对象,可以是结构体或字符串

WBOY
发布: 2024-02-09 08:48:29
转载
940 人浏览过

将 YAML 解组为复杂对象,可以是结构体或字符串

php小编草莓介绍:YAML是一种轻量级的数据序列化格式,它具有简洁易读的语法,被广泛用于配置文件和数据交换。在PHP中,我们可以使用YAML解析库将YAML数据解组为复杂对象,这些对象可以是结构体或字符串。这为开发人员提供了一种方便的方式来处理和操作配置文件和其他数据。无论是构建复杂的应用程序还是简化配置管理,YAML解析在PHP中发挥着重要的作用。

问题内容

尝试将 yaml 解组为复杂对象,例如 map[string]map[interface{}]string。 问题是我希望能够区分 stringsource 之间的 interface{} 部分,这是一个结构。

type source struct {
    id     string `yaml:"id"`
    name   string `yaml:"name"`
    logoid string `yaml:"logoid"`
    url    string `yaml:"url"`
}

type unft struct {
    itemmeta map[string]map[interface{}]string `yaml:"item_meta"`
    // could be
    // itemmeta map[string]map[string]string `yaml:"item_meta"`
    // or
    // itemmeta map[string]map[source]string `yaml:"item_meta"`
}
登录后复制

显然 yaml 不知道如何解组到 source 结构中,所以我必须实现 unmarshaler 接口:

type unmarshaler interface {
    unmarshalyaml(value *node) error
}
登录后复制

但我不太了解解组过程的总体情况。一般来说,我假设我必须手动遍历 *yaml.node 并在每个节点上调用 func unmarshalyaml(value *node) error

package main

import (
    "fmt"

    "gopkg.in/yaml.v3"
)

type Source struct {
    ID     string `json:"id"`
    Name   string `json:"name"`
    LogoID string `json:"logoId"`
    URL    string `json:"url"`
}

var data = `
unf:
    item_meta:
      source:
           !struct
           ? id: "data-watch" 
             name: "DataWatch"
             logoid: "data-watch"
             url: "https"
           : "product_any('SS')"
      public_usage:
        "": "source_any('SDF')"
        "provider": "source_any('ANO')"`

type UNFT struct {
    ItemMeta map[string]map[interface{}]string `yaml:"item_meta"`
}

type MetaConverterConfigT struct {
    UNFT UNFT `yaml:"unf"`
}

func main() {
    cfg := MetaConverterConfigT{}

    err := yaml.Unmarshal([]byte(data), &cfg)
    if err != nil {
        fmt.Println("%w", err)
    }

    fmt.Println(cfg)
}

func (s *UNFT) UnmarshalYAML(n *yaml.Node) error {
    var cfg map[string]map[interface{}]string
    if err := n.Decode(&cfg); err != nil {
        fmt.Println("%w", err)
    }

    return nil
}
登录后复制

去游乐场

解决方法

type metakey struct {
    string string
    source source
}

func (k *metakey) unmarshalyaml(n *yaml.node) error {
    if n.tag == "!!str" {
        return n.decode(&k.string)
    }
    if n.tag == "!!map" {
        return n.decode(&k.source)
    }
    return fmt.errorf("unsupported metakey type")
}

// ...

type unft struct {
    itemmeta map[string]map[metakey]string `yaml:"item_meta"`
}
登录后复制

https://www.php.cn/link/50f9999b2ee27e222c5513e945e9ea9c

如果您需要保持映射类型不变,即不添加自定义键类型,那么您也可以在 unft 上实现解组器,只需使用 any 进行重新映射即可:

type UNFT struct {
    ItemMeta map[string]map[any]string `yaml:"item_meta"`
}

func (u *UNFT) UnmarshalYAML(n *yaml.Node) error {
    var obj struct {
        ItemMeta map[string]map[MetaKey]string `yaml:"item_meta"`
    }
    if err := n.Decode(&obj); err != nil {
        return err
    }

    u.ItemMeta = make(map[string]map[any]string, len(obj.ItemMeta))
    for k, v := range obj.ItemMeta {
        m := make(map[any]string, len(v))
        for k, v := range v {
            if k.Source != (Source{}) {
                m[k.Source] = v
            } else {
                m[k.String] = v
            }
        }
        u.ItemMeta[k] = m
    }
    return nil
}
登录后复制

https://www.php.cn/link/543378fb36a83810ded2d725f2b6c883

以上是将 YAML 解组为复杂对象,可以是结构体或字符串的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:stackoverflow.com
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板