Fix up the MapWalk function so that it properly handles nested map[interface{}]interface{} (#5774)

This commit is contained in:
Matt Keeler 2019-05-02 14:43:54 -04:00 committed by GitHub
parent eb24e73cfd
commit 8c386277ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 20 deletions

2
go.mod
View File

@ -95,7 +95,7 @@ require (
github.com/mitchellh/go-testing-interface v1.0.0 github.com/mitchellh/go-testing-interface v1.0.0
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452
github.com/mitchellh/mapstructure v1.1.2 github.com/mitchellh/mapstructure v1.1.2
github.com/mitchellh/reflectwalk v0.0.0-20170726202117-63d60e9d0dbc github.com/mitchellh/reflectwalk v1.0.1
github.com/oklog/run v0.0.0-20180308005104-6934b124db28 // indirect github.com/oklog/run v0.0.0-20180308005104-6934b124db28 // indirect
github.com/onsi/gomega v1.4.2 // indirect github.com/onsi/gomega v1.4.2 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect

4
go.sum
View File

@ -256,8 +256,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v0.0.0-20170726202117-63d60e9d0dbc h1:gqYjvctjtX4GHzgfutJxZpvZ7XhGwQLGR5BASwhpO2o= github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v0.0.0-20170726202117-63d60e9d0dbc/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=

View File

@ -95,8 +95,31 @@ func (w *mapWalker) Map(m reflect.Value) error {
func (w *mapWalker) MapElem(m, k, v reflect.Value) error { func (w *mapWalker) MapElem(m, k, v reflect.Value) error {
w.csData = k w.csData = k
w.csKey = append(w.csKey, k) w.csKey = append(w.csKey, k)
w.lastValue = v w.lastValue = v
// We're looking specifically for map[interface{}]interface{}, but the
// values in a map could be wrapped up in interface{} so we need to unwrap
// that first. Therefore, we do three checks: 1.) is it valid? so we
// don't panic, 2.) is it an interface{}? so we can unwrap it and 3.)
// after unwrapping the interface do we have the map we expect?
if !v.IsValid() {
return nil
}
if v.Kind() != reflect.Interface {
return nil
}
if inner := v.Elem(); inner.Type() == typMapIfaceIface {
// map[interface{}]interface{}, attempt to weakly decode into string keys
var target map[string]interface{}
if err := mapstructure.WeakDecode(v.Interface(), &target); err != nil {
return err
}
m.SetMapIndex(k, reflect.ValueOf(target))
}
return nil return nil
} }

View File

@ -38,20 +38,21 @@ func TestMapWalk(t *testing.T) {
}, },
unexpected: true, unexpected: true,
}, },
// TODO(banks): despite the doc comment, MapWalker doesn't actually fix // ensure nested maps get processed correctly
// these cases yet. Do that in a later PR. "nested": tcase{
// "map iface": tcase{ input: map[string]interface{}{
// input: map[string]interface{}{ "foo": map[interface{}]interface{}{
// "foo": map[interface{}]interface{}{ "bar": []uint8("baz"),
// "bar": "baz", },
// }, "bar": []uint8("baz"),
// }, },
// expected: map[string]interface{}{ expected: map[string]interface{}{
// "foo": map[string]interface{}{ "foo": map[string]interface{}{
// "bar": "baz", "bar": "baz",
// }, },
// }, "bar": "baz",
// }, },
},
} }
for name, tcase := range cases { for name, tcase := range cases {

1
vendor/github.com/mitchellh/reflectwalk/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/mitchellh/reflectwalk

View File

@ -230,7 +230,8 @@ func walkMap(v reflect.Value, w interface{}) error {
ew.Enter(MapValue) ew.Enter(MapValue)
} }
if err := walk(kv, w); err != nil { // get the map value again as it may have changed in the MapElem call
if err := walk(v.MapIndex(k), w); err != nil {
return err return err
} }

2
vendor/modules.txt vendored
View File

@ -377,7 +377,7 @@ github.com/mitchellh/go-testing-interface
github.com/mitchellh/hashstructure github.com/mitchellh/hashstructure
# github.com/mitchellh/mapstructure v1.1.2 # github.com/mitchellh/mapstructure v1.1.2
github.com/mitchellh/mapstructure github.com/mitchellh/mapstructure
# github.com/mitchellh/reflectwalk v0.0.0-20170726202117-63d60e9d0dbc # github.com/mitchellh/reflectwalk v1.0.1
github.com/mitchellh/reflectwalk github.com/mitchellh/reflectwalk
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/modern-go/concurrent github.com/modern-go/concurrent