Open bluebrown opened 2 years ago
I'd like to add onto this. Not sure if this is intentional, but when Unmarshalling into a pre-existing struct, the yaml.Unmarshal
seems to always return a map[interface{}]interface{}
, with the only solution being to type assert it to the desired type. In contrast, json.Unmarshal
always returns the same type as the struct passed to it. I'll try to provide an example later.
Note: from the YAML 1.2 spec
The content of a mapping node is an unordered set of key/value node pairs, with the restriction that each of the keys is unique. YAML places no further restrictions on the nodes. In particular, keys may be arbitrary nodes, the same node may be used as the value of several key/value pairs and a mapping could even contain itself as a key or a value.
Same issue - see https://go.dev/play/p/OjcJTBbcTFA
Encoding result of map[bool]any
:
s := map[string]any{
"question": map[bool]any{
true: "Positive",
false: "Negative",
},
}
Is OK:
question:
false: Negative
true: Positive
But when decode this - decoded as map[interface{}]interface{}
, not map[bool]any
(or map[string]any
):
map[string]interface{}{
"question": map[interface{}]interface{}{
false: "Negative",
true: "Positive",
},
}
I actually don't see any reason why map[interface{}]interface{} is required
I wanted to check if there are any null values in yaml, map[any]any is very useful in that case.
Edit - v3 decodes to map[string]any and map[any]any only, so it is fine, handling an extra case is alright.
The standard lib JSON package decodes objects into
map[string]interface{}
. That is useful when trying to marshal the result again.This YAML package decodes into
map[interface{}]interface{}
which is causing errors when trying to marshal the result.I actually don't see any reason why
map[interface{}]interface{}
is required. Object keys in, YAML and JSON, can only be strings, there is no other option. At least as far as I can tell.https://play.golang.com/p/KwXpFr8KC08
Example
Code: ```golang package main import ( "encoding/json" "fmt" "io" "strings" "gopkg.in/yaml.v2" ) func main() { fmt.Printf("JSON\n-------\n") test(decodeJson) fmt.Printf("\nYAML\n-------\n") test(decodeYaml) } func test(decode func(s string) interface{}) { v := decode(`{"foo": "bar"}`) fmt.Printf("%T\n", v) b, err := json.MarshalIndent(v, "", " ") if err != nil { panic(err) } println(string(b)) } func decodeYaml(s string) interface{} { dec := yaml.NewDecoder(strings.NewReader(s)) var v interface{} for { if err := dec.Decode(&v); err == io.EOF { break } else if err != nil { panic(err) } } return v } func decodeJson(s string) interface{} { dec := json.NewDecoder(strings.NewReader(s)) var v interface{} for { if err := dec.Decode(&v); err == io.EOF { break } else if err != nil { panic(err) } } return v } ``` Output: ``` JSON ------- map[string]interface {} { "foo": "bar" } YAML ------- map[interface {}]interface {} panic: json: unsupported type: map[interface {}]interface {} goroutine 1 [running]: main.test(0x542a00) /home/blue/projects/own/cmdpipe/main.go:24 +0x106 main.main() /home/blue/projects/own/cmdpipe/main.go:16 +0x7b exit status 2 ```