Unmarshal YAML menjadi objek kompleks, sama ada struct atau rentetan

WBOY
Lepaskan: 2024-02-09 08:48:29
ke hadapan
889 orang telah melayarinya

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

Penyunting PHP Strawberry Pengenalan: YAML ialah format siri data yang ringan Ia mempunyai sintaks yang ringkas dan mudah dibaca dan digunakan secara meluas untuk fail konfigurasi dan pertukaran data. Dalam PHP, kita boleh menggunakan perpustakaan penghuraian YAML untuk menyahmarshal data YAML ke dalam objek kompleks, yang boleh menjadi struktur atau rentetan. Ini memberikan pembangun cara yang mudah untuk mengendalikan dan memanipulasi fail konfigurasi dan data lain. Sama ada membina aplikasi kompleks atau memudahkan pengurusan konfigurasi, penghuraian YAML memainkan peranan penting dalam PHP.

Kandungan soalan

Cuba unmarshal yaml menjadi objek kompleks, seperti map[string]map[interface{}]string. Masalahnya ialah saya ingin dapat membezakan bahagian stringsource 之间的 interface{} iaitu struktur.

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"`
}
Salin selepas log masuk

Nampaknya yaml tidak tahu bagaimana untuk membuka source 结构中,所以我必须实现 unmarshaler antara muka:

type unmarshaler interface {
    unmarshalyaml(value *node) error
}
Salin selepas log masuk

Tetapi saya tidak begitu memahami keadaan keseluruhan proses unmarshalling. Secara umum, saya menganggap saya perlu mengulang *yaml.node 并在每个节点上调用 func unmarshalyaml(value *node) error secara manual.

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
}
Salin selepas log masuk

Pergi ke taman hiburan

Penyelesaian

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"`
}
Salin selepas log masuk

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

Jika anda perlu mengekalkan jenis yang dipetakan tidak berubah, iaitu tanpa menambah jenis kunci tersuai, maka anda juga boleh melaksanakan unmarshaller pada unft dan hanya memetakan semula menggunakan 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
}
Salin selepas log masuk

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

Atas ialah kandungan terperinci Unmarshal YAML menjadi objek kompleks, sama ada struct atau rentetan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!