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

Mergo not overriding destination with source #228

Closed
RomilShah opened this issue Dec 2, 2022 · 2 comments
Closed

Mergo not overriding destination with source #228

RomilShah opened this issue Dec 2, 2022 · 2 comments

Comments

@RomilShah
Copy link

RomilShah commented Dec 2, 2022

I am trying to merge values of 2 JSON into 1, where value of source should override value of destination. It is working fine for most the cases except for the case where value of 1 hashmap is string and other value is another hashmap. Below is the code snipped

package main

import (
	"encoding/json"
	"fmt"

	"github.com/imdario/mergo"
)

var (
	a = "{\"a\": \"60\"}"
	b = "{\"a\": { \"name\":\"asprin\", \"dose\":0.12,\"stt\":true} }"
)

func main() {
	var source, destination map[string]interface{}

	err := json.Unmarshal([]byte(a), &destination)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal([]byte(b), &source)
	if err != nil {
		panic(err)
	}

	fmt.Println(destination, source)
	err = mergo.MergeWithOverwrite(&destination, &source, mergo.WithOverride, mergo.WithTypeCheck)
	if err != nil {
		panic(err)
	}
	fmt.Println(&destination, "  <-- result")

}

playground: https://go.dev/play/p/BTmRc7wf6Js

Current output is

&map[a:60] <-- result which is value of destination. Mergo is not changing anything

Excepted output is

map[a:map[dose:0.12 name:asprin stt:true]] <--result

or at-least give error that it is not possible to merge hashmap to string`

@svengreb
Copy link

svengreb commented Dec 29, 2022

It looks like you're looking for something like github.com/mitchellh/mapstructure instead which is exactly tailored for use cases “where you don't quite know the structure of the underlying data until you read a part of it“. In your case a is a number in the first map, bur changes to a object in the second which is a different type. mergo is strong when it comes to merging structs o the same type.
mergo provides a Map function, but mapstructure fits better because it is the main goal of the project to handle maps.

@darccio
Copy link
Owner

darccio commented Sep 11, 2023

@RomilShah This code works as you expected:

package main

import (
	"encoding/json"
	"fmt"

	"dario.cat/mergo"
)

var (
	a = "{\"a\": \"60\"}"
	b = "{\"a\": { \"name\":\"asprin\", \"dose\":0.12,\"stt\":true} }"
)

func main() {
	var source, destination map[string]interface{}

	err := json.Unmarshal([]byte(a), &destination)
	if err != nil {
		panic(err)
	}
	err = json.Unmarshal([]byte(b), &source)
	if err != nil {
		panic(err)
	}

	err = mergo.Map(&destination, source, mergo.WithOverride)
	if err != nil {
		panic(err)
	}
	fmt.Println(destination, "  <-- result")

}

It even works if you use Merge instead of Map, making mergo equivalent to mapstructure. Merging structs or maps is the same logic, although in Mergo Map is a specialized case of Merge.

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

3 participants