Skip to content
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

Invalid merge of two map[string]interface{} #91

Closed
dshylov opened this issue Nov 19, 2018 · 9 comments
Closed

Invalid merge of two map[string]interface{} #91

dshylov opened this issue Nov 19, 2018 · 9 comments

Comments

@dshylov
Copy link

dshylov commented Nov 19, 2018

Merge of

func main() {
	map1 := map[string]interface{}{
		"first": 1,
	}
	map2 := map[string]interface{}{
		"first": map[string]interface{}{
			"second" : 2,
		},
	}

	mergo.Merge(&map1, map2)

	fmt.Println(map1)
}

will returns

map[first:1]

@dshylov
Copy link
Author

dshylov commented Nov 19, 2018

Result with mergo.WithOverride is the same

@birdayz
Copy link

birdayz commented Nov 27, 2018

i've just discovered the same issue. is this intended?

@dshylov
Copy link
Author

dshylov commented Dec 4, 2018

@imdario any updates?

@0x1mason
Copy link

0x1mason commented Jan 2, 2019

@dshylov From README You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. You've got different types.

@darccio
Copy link
Owner

darccio commented Jan 23, 2019

@0x1mason, actually, maps are more flexible. Both maps have the same type map[string]interface{} so they should count as "same-type maps" but I'll check it.

@Overbryd
Copy link

I found the same.
Triggered in my helm templating. Both are of type map[string]interface{}.
Helm uses Masterminds/sprig to provide merge functionality for their template values.

This breaks the idea and "contract" implemented here: https://github.com/Masterminds/sprig/blob/master/dict.go#L80
I will also create an issue on their side.

I whipped up an example that shows the unexpected behaviour:

package main

import (
  "fmt"
  "github.com/imdario/mergo"
)

func main() {
  map1 := map[string]interface{}{
    "deep": map[string]interface{}{
      "enabled": true,
    },
    "key": "default",
  }
  map2 := map[string]interface{}{
    "deep": map[string]interface{}{
      "enabled": false,
    },
    "key": "overwritten",
  }

  mergo.Merge(&map1, map2)

  fmt.Println(map1)
}

Expected output

map[deep:map[enabled:false] key:overwritten]
Actual output
$ go get -u github.com/imdario/mergo
map[deep:map[enabled:true] key:default]

@vdemeester
Copy link
Collaborator

@Overbryd if you use mergo.WithOverride in the Merge methods, it should work..

package main

import (
  "fmt"
  "github.com/imdario/mergo"
)

func main() {
  map1 := map[string]interface{}{
    "deep": map[string]interface{}{
      "enabled": true,
    },
    "key": "default",
  }
  map2 := map[string]interface{}{
    "deep": map[string]interface{}{
      "enabled": false,
    },
    "key": "overwritten",
  }

  mergo.Merge(&map1, map2)

  fmt.Println(map1)
}

This will print map[deep:map[enabled:false] key:overwritten]

@Overbryd
Copy link

@vdemeester thanks, I can confirm that mergo.Merge(&map1, map2, mergo.WithOverride) works as expected.

@darccio
Copy link
Owner

darccio commented Jul 17, 2020

Solved fixing #143 by reverting PR #105

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants