Reputation: 31604
I have next yaml, if I validate it in online yaml website, it said it's valid:
- {"foo": "1", "bar": "2"}
Then, I write a code to parse the value 1
and 2
from this yaml as next:
test.go:
package main
import "gopkg.in/yaml.v2"
import "fmt"
type Config struct {
Foo string
Bar string
}
type Configs struct {
Cfgs []Config `foobar`
}
func main() {
//var data = `
// foobar:
// - foo: 1
// bar: 2
//`
var data = `
- foo: 1
bar: 2
`
source := []byte("foobar:" + data)
var configs Configs
err := yaml.Unmarshal(source, &configs)
if err != nil {
fmt.Println("error: %v", err)
}
fmt.Printf("--- configs:\n%v\n\n", configs)
fmt.Println(configs.Cfgs[0].Foo)
fmt.Println(configs.Cfgs[0].Bar)
}
It works ok as next:
shubuntu1@shubuntu1:~/20210810$ go run test.go
--- configs:
{[{1 2}]}
1
2
What's the problem?
You could see I made a workaround here as next to add special foobar
key before the original yaml, then I could use type Configs struct
to unmarshal it:
From
- foo: 1
bar: 2
to
foobar:
- foo: 1
bar: 2
So, if I don't use the workaround to add a prefix foobar:
, how could I directly parse - {"foo": 1, "bar": 2}
?
Upvotes: 4
Views: 10730
Reputation: 879
Since the question has already been answered, I thought I might add something to the discussion:
var data = `
- foo: 1
bar: 2
`
The data variable here, the way you wrote it, will include the indentation at the start of each line.
The extra indentation here WILL be passed into yaml.Unmarshal()
alongside all the actual yaml data, which can mess things up since gofmt
formats your code to use TAB as indentation and TAB indentation is forbidden in yaml (https://stackoverflow.com/a/19976827/7509248).
If you use tab as indentation in yaml, an error like this will be thrown when trying to unmarshal it:
yaml: line 1: found a tab character that violates indentation
Preferably, you want to load data
from a separate file to avoid such issue.
package main
import (
"fmt"
"io/ioutil"
"gopkg.in/yaml.v2"
)
type Config struct {
Foo string
Bar string
}
func main() {
var configs []Config
source, err := ioutil.ReadFile("config.yaml")
if err != nil {
fmt.Printf("failed reading config file: %v\n", err)
}
err = yaml.Unmarshal(source, &configs)
if err != nil {
fmt.Printf("error: %v\n", err)
}
fmt.Printf("config:\n%+v\n", configs)
}
config.yaml:
- foo: 1
bar: 2
output:
config:
[{Foo:1 Bar:2}]
Upvotes: 2
Reputation: 13496
Since your YAML
data is an array, unmarshal it to an array of Config
structure.
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type Config struct {
Foo string
Bar string
}
func main() {
var configs []Config
var data = `
- foo: 1
bar: 2
`
err := yaml.Unmarshal([]byte(data), &configs)
if err != nil {
panic(err)
}
fmt.Println(configs)
}
Output:
[{1 2}]
Try on - Go Playground
Upvotes: 5