首頁  >  文章  >  後端開發  >  將 YAML 解組為複雜對象,可以是結構體或字串

將 YAML 解組為複雜對象,可以是結構體或字串

WBOY
WBOY轉載
2024-02-09 08:48:29923瀏覽

将 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刪除