php小编草莓介绍:YAML是一种轻量级的数据序列化格式,它具有简洁易读的语法,被广泛用于配置文件和数据交换。在PHP中,我们可以使用YAML解析库将YAML数据解组为复杂对象,这些对象可以是结构体或字符串。这为开发人员提供了一种方便的方式来处理和操作配置文件和其他数据。无论是构建复杂的应用程序还是简化配置管理,YAML解析在PHP中发挥着重要的作用。
问题内容
尝试将 yaml 解组为复杂对象,例如 map[string]map[interface{}]string
。
问题是我希望能够区分 string
和 source
之间的 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