Heim  >  Artikel  >  Backend-Entwicklung  >  Entpacken Sie YAML in komplexe Objekte, entweder Strukturen oder Strings

Entpacken Sie YAML in komplexe Objekte, entweder Strukturen oder Strings

WBOY
WBOYnach vorne
2024-02-09 08:48:29865Durchsuche

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

PHP Editor Strawberry Einführung: YAML ist ein leichtes Datenserialisierungsformat. Es verfügt über eine prägnante und leicht lesbare Syntax und wird häufig für Konfigurationsdateien und den Datenaustausch verwendet. In PHP können wir die YAML-Parsing-Bibliothek verwenden, um YAML-Daten in komplexe Objekte zu entpacken, bei denen es sich um Strukturen oder Strings handeln kann. Dies bietet Entwicklern eine bequeme Möglichkeit, Konfigurationsdateien und andere Daten zu verwalten und zu bearbeiten. Unabhängig davon, ob Sie komplexe Anwendungen erstellen oder das Konfigurationsmanagement vereinfachen, spielt das YAML-Parsing in PHP eine wichtige Rolle.

Frageninhalt

Versuchen Sie, Yaml in komplexe Objekte wie map[string]map[interface{}]string zu zerlegen. Das Problem ist, dass ich den stringsource 之间的 interface{}-Teil unterscheiden möchte, der eine Struktur ist.

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

Anscheinend weiß das Yaml nicht, wie man es in die source 结构中,所以我必须实现 unmarshaler-Schnittstelle entmarshallt:

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

Aber ich verstehe die Gesamtsituation des Unmarshalling-Prozesses nicht ganz. Im Allgemeinen gehe ich davon aus, dass ich *yaml.node 并在每个节点上调用 func unmarshalyaml(value *node) error manuell durchlaufen muss.

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
}

Gehen Sie in den Vergnügungspark

Lösung

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

Wenn Sie den zugeordneten Typ unverändert lassen müssen, d. h. ohne einen benutzerdefinierten Schlüsseltyp hinzuzufügen, können Sie den Unmarshaller auch auf unft implementieren und ihn einfach mit any:

neu zuordnen
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

Das obige ist der detaillierte Inhalt vonEntpacken Sie YAML in komplexe Objekte, entweder Strukturen oder Strings. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen