Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Unmarshal YAML menjadi objek kompleks, sama ada struct atau rentetan

Unmarshal YAML menjadi objek kompleks, sama ada struct atau rentetan

WBOY
WBOYke hadapan
2024-02-09 08:48:29865semak imbas

将 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"`
}

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

type unmarshaler interface {
    unmarshalyaml(value *node) error
}

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
}

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"`
}

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
}

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!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam