Reputation: 35
I use viper. I'm trying to get info from structs with yml-config.
type Config struct {
Account User `mapstructure:"user"`
}
type User struct {
Name string `mapstructure:"name"`
Contacts []Contact `mapstructure:"contact"`
}
type Contact struct {
Type string `mapstructure:"type"`
Value string `mapstructure:"value"`
}
func Init() *Config {
conf := new(Config)
viper.SetConfigType("yaml")
viper.ReadInConfig()
...
viper.Unmarshal(conf)
return conf
}
...
config := Init()
...
for _, contact := range config.Account.Contacts {
type := contact.type
vlaue := contact.value
}
And config.yml
user:
name: John
contacts:
email:
type: email
value: [email protected]
skype:
type: skype
value: skypeacc
Can I get structure items like this? I could not get contact data like that. Is it possible?
Upvotes: 0
Views: 573
Reputation: 311720
I think the only significant problem is that in your data structures you've declared Contacts
as a list, but in your YAML file it's a dictionary. If you structure your input file like this:
user:
name: John
contacts:
- type: email
value: [email protected]
- type: skype
value: skypeacc
Then you can read it like this:
package main
import (
"fmt"
"github.com/spf13/viper"
)
type Config struct {
User User
}
type User struct {
Name string
Contacts []Contact
}
type Contact struct {
Type string
Value string
}
func main() {
var cfg Config
viper.SetConfigName("config")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(err)
}
viper.Unmarshal(&cfg)
fmt.Println("user: ", cfg.User.Name)
for _, contact := range cfg.User.Contacts {
fmt.Println(" ", contact.Type, ": ", contact.Value)
}
}
The above code is runnable as-is; you should just be able to drop it into a file and build it. When I run the above example, I get as output:
user: John
email : [email protected]
skype : skypeacc
Upvotes: 0
Reputation: 191
If I'm getting right what you want to achieve, and based on the for
loop you provided;
user:
name: John
contacts:
- type: email
value: [email protected]
- type: skype
value: skypeacc
- type: email
value: [email protected]
Contacts
slice. It should match the YAML key;type User struct {
Name string `mapstructure:"name"`
Contacts []Contact `mapstructure:"contacts"`
}
If you wish to keep the original YAML file structure you have to provide a tag (and the corresponding struct field) for each YAML key, so looping over it wouldn't be possible out of the box, because email
and skype
are parsed as struct fields. An example of the struct for the original YAML file would be;
type Config struct {
Account User `mapstructure:"user"`
}
type User struct {
Name string `mapstructure:"name"`
Contacts Contacts `mapstructure:"contacts"`
}
type Contacts struct {
Email Contact `mapstructure:"email"`
Skype Contact `mapstructure:"skype"`
}
type Contact struct {
Type string `mapstructure:"type"`
Value string `mapstructure:"value"`
}
Upvotes: 1