-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
map[interface{}]interface{} on a map[string]interface{} #139
Comments
I'm having trouble with this too. Even if I unmarshal into a Is it possible to analyse the type of the interface passed to unmarshal then use the same type for recursively unmarshalling all the way down? |
I'm not sure that would work in all cases. I also had this problem and made a custom unmarshaller in github.com/elastic/beats:libbeat/common/mapstr.go that converts the keys of nested maps to strings so that the unmarshalled data can always be marshalled into JSON. |
The approach of @magnusbaeck works like a charm! I changed unmarshalYAML a bit as well as cleanUpMapValue in order to fit my needs (eg. it has now the same signature as yaml.Unmarshal() and ints, bool et al are not quoted since this works fine with encoding/json)... https://github.com/unprofession-al/gerty/blob/master/api/helpers.go It would be nice to see this in go-yaml as "compatibility mode". |
+1 |
1 similar comment
+1 |
+1 |
1 similar comment
+1 |
I modified the code from the suggestion above and it works nicely. Would be nicer not having to do it thought. // Copyright (c) 2015-2016 Michael Persson
// Copyright (c) 2012–2015 Elasticsearch <http://www.elastic.co>
//
// Originally distributed as part of "beats" repository (https://github.com/elastic/beats).
// Modified specifically for "iodatafmt" package.
//
// Distributed underneath "Apache License, Version 2.0" which is compatible with the LICENSE for this package.
package yaml_mapstr
import (
// Base packages.
"fmt"
// Third party packages.
"gopkg.in/yaml.v2"
)
// Unmarshal YAML to map[string]interface{} instead of map[interface{}]interface{}.
func Unmarshal(in []byte, out interface{}) error {
var res interface{}
if err := yaml.Unmarshal(in, &res); err != nil {
return err
}
*out.(*interface{}) = cleanupMapValue(res)
return nil
}
// Marshal YAML wrapper function.
func Marshal(in interface{}) ([]byte, error) {
return yaml.Marshal(in)
}
func cleanupInterfaceArray(in []interface{}) []interface{} {
res := make([]interface{}, len(in))
for i, v := range in {
res[i] = cleanupMapValue(v)
}
return res
}
func cleanupInterfaceMap(in map[interface{}]interface{}) map[string]interface{} {
res := make(map[string]interface{})
for k, v := range in {
res[fmt.Sprintf("%v", k)] = cleanupMapValue(v)
}
return res
}
func cleanupMapValue(v interface{}) interface{} {
switch v := v.(type) {
case []interface{}:
return cleanupInterfaceArray(v)
case map[interface{}]interface{}:
return cleanupInterfaceMap(v)
case string:
return v
default:
return fmt.Sprintf("%v", v)
}
} |
+1 I'm currently maintaining a fork with a one line change to work around this issue. To be clear: I believe the library's design is correct given the way YAML handles boolean keys. However, I'd be willing to guess that a majority of implementations don't care about boolean keys and would rather have map keys default to strings. Maybe exporting |
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Works around the following yaml issue: go-yaml/yaml#139
Oh my, extremely sorry for this massive spam. Rebases ¯\(ツ)/¯ |
yaml.v3 unmarshals to map[interface{}]interface{} if using yaml-anchors. Because helm converts yaml to json we have to unmarshal to map[string]interface{} instead of map[interface{}]interface{}. To achieve this we simply replace the yaml provider "gopkg.in/yaml.v3" with "sigs.k8s.io/yaml". For more details see go-yaml/yaml#139
a.go
go run *go
|
The recent switch to mergo throws in a yaml version which is affected by go-yaml/yaml#139, and caused rancher/elemental-toolkit#1189. Updating to yaml.v3 where it was affected. Note mergo still uses v2, so this can be problematic on other areas darccio/mergo#206.
NOTE: upgrade from implicit gopkg.in/yaml.v2 to explicit gopkg.in/yaml.v3 to fix go-yaml/yaml#139
@aanm, @niemeyer, please close this issue since it was fixed with v3 (as noted by some comments above as well): package main
import (
"fmt"
"reflect"
"gopkg.in/yaml.v3"
)
var data = `---
foo-map:
something: "thing"
newstruct:
otherstruct:
-
foo-bar: 12345
bar: "bar"`
type FooStruct struct {
FooMap map[string]interface{} `yaml:"foo-map,omitempty"`
}
func main() {
var foo FooStruct
err := yaml.Unmarshal([]byte(data), &foo)
if err != nil {
fmt.Printf("error %+v", err)
}
for k, v := range foo.FooMap {
fmt.Printf("type=%+v key=%+v type=%+v value=%+v\n", reflect.TypeOf(k), k, reflect.TypeOf(v), v)
}
// output:
// type=string key=newstruct type=map[string]interface {} value=map[bar:bar otherstruct:[map[foo-bar:12345]]]
// type=string key=something type=string value=thing
} |
Sorry to be persistent with this. I wasn't aware that yaml was able to have different types has keys than string. However, with the following example I see that
newstruct
is being considered has amap[interface{}]interface{}
, is it a bug or is something I should expect?The text was updated successfully, but these errors were encountered: