Home  >  Article  >  Backend Development  >  Unmarshal yaml mapping dict keys to structure properties

Unmarshal yaml mapping dict keys to structure properties

WBOY
WBOYforward
2024-02-09 15:40:29950browse

解组 yaml 将 dict 键映射到结构属性

php Xiaobian Xigua today introduces you to a very useful technique - unmarshalling YAML into a dictionary and mapping keys to structural attributes. YAML is a lightweight data serialization format commonly used for configuration files and data exchange. By unmarshalling YAML, we can convert it into a dictionary, and then map the dictionary keys to structural properties, making it easier for us to perform further operations and processing in the code. This technique is very useful when dealing with configuration files or loading data from external data sources. Let's take a look at the specific implementation method!

Question content

I did search here for a while but did not find a suitable answer:

I'm trying to unmarshal yaml dict keys onto attributes of a struct rather than mapped keys. Given this yaml

commands:
    php:
        service: php
        bin: /bin/php
    node:
        service: node
        bin: /bin/node

I was able to unmarshal it into a structure like this:

type config struct {
    commands map[string]struct {
        service string
        bin     string
    }
}

But how can I unpack it into a structure like this:

type Config struct {
    Commands []struct {
        Name    string    // <-- this should be key from the yaml (i.e. php or node)
        Service string
        Bin     string
    }
}

Thanks in advance for your help

Workaround

You can write a custom unmarshaller like this (on the go playground):

package main

import (
    "fmt"

    "gopkg.in/yaml.v3"
)

var input []byte = []byte(`
commands:
    php:
        service: php
        bin: /bin/php
    node:
        service: node
        bin: /bin/node
`)

type Command struct {
    Service string
    Bin     string
}

type NamedCommand struct {
    Command
    Name string
}

type NamedCommands []NamedCommand

type Config struct {
    Commands NamedCommands
}

func (p *NamedCommands) UnmarshalYAML(value *yaml.Node) error {
    if value.Kind != yaml.MappingNode {
        return fmt.Errorf("`commands` must contain YAML mapping, has %v", value.Kind)
    }
    *p = make([]NamedCommand, len(value.Content)/2)
    for i := 0; i < len(value.Content); i += 2 {
        var res = &(*p)[i/2]
        if err := value.Content[i].Decode(&res.Name); err != nil {
            return err
        }
        if err := value.Content[i+1].Decode(&res.Command); err != nil {
            return err
        }
    }
    return nil
}

func main() {
    var f Config
    var err error
    if err = yaml.Unmarshal(input, &f); err != nil {
        panic(err)
    }
    for _, cmd := range f.Commands {
        fmt.Printf("%+v\n", cmd)
    }
}

I've split the command data into command and namedcommand to make the code simpler since you can just call decode to provide the embedded command The value of the structure. If everything is in the same struct, you'll need to manually map keys to struct fields.

The above is the detailed content of Unmarshal yaml mapping dict keys to structure properties. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete