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

Unmarshal yaml mapping dict keys to structure properties

WBOY
Release: 2024-02-09 15:40:29
forward
985 people have browsed it

解组 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
Copy after login

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

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

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
    }
}
Copy after login

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)
    }
}
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template