Skip to content

MergeWithOverwrite behavior on struct field inside a map #14

@accerqueira

Description

@accerqueira

Hi,

I would expect that fields from a struct on a map would only be overwritten by MergeWithOverwrite if the src struct field was not empty valued, but according to the following test, it seems to be overwriting anyway on map to struct and map to struct pointer.

package mergo_test

import "testing"
import "github.com/imdario/mergo"

type Struct struct {
    Value string
}
type StructOfStruct struct {
    Value Struct
}

type MapToStructPtr map[string]*Struct
type MapToStruct map[string]Struct

func TestMapToStructPtr(t *testing.T) {
    var dst = make(MapToStructPtr)
    dst["a"] = &Struct{Value: "1"}
    var src = make(MapToStructPtr)
    src["a"] = &Struct{}
    var expect = make(MapToStructPtr)
    expect["a"] = &Struct{Value: "1"}

    if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
        t.FailNow()
    }

    for k, _ := range expect {
        if ((expect[k] == nil) != (dst[k] == nil)) || (expect[k] != nil && dst[k].Value != expect[k].Value) {
            t.Errorf("Test failed:\ngot  :\n dst[\"%s\"] = %#v\n\nwant :\n dst[\"%s\"] = %#v\n\n", k, dst[k], k, expect[k])
        }
    }
}

func TestMapToStruct(t *testing.T) {
    var dst = make(MapToStruct)
    dst["a"] = Struct{Value: "1"}
    var src = make(MapToStruct)
    src["a"] = Struct{}
    var expect = make(MapToStruct)
    expect["a"] = Struct{Value: "1"}

    if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
        t.FailNow()
    }

    for k, _ := range expect {
        if dst[k].Value != expect[k].Value {
            t.Errorf("Test failed:\ngot  :\n dst[\"%s\"] = %#v\n\nwant :\n dst[\"%s\"] = %#v\n\n", k, dst[k], k, expect[k])
        }
    }
}

func TestStruct(t *testing.T) {
    var dst = Struct{Value: "1"}
    var src = Struct{}
    var expect = Struct{Value: "1"}

    if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
        t.FailNow()
    }

    if dst.Value != expect.Value {
        t.Errorf("Test failed:\ngot  :\n dst = %#v\n\nwant :\n dst = %#v\n\n", dst, expect)
    }
}

func TestStructOfStruct(t *testing.T) {
    var dst = StructOfStruct{Value: Struct{"1"}}
    var src = StructOfStruct{}
    var expect = StructOfStruct{Value: Struct{"1"}}

    if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
        t.FailNow()
    }

    if dst.Value != expect.Value {
        t.Errorf("Test failed:\ngot  :\n dst = %#v\n\nwant :\n dst = %#v\n\n", dst, expect)
    }
}

go test -v mergo_test.go gives me the following output

=== RUN TestMapToStructPtr
--- FAIL: TestMapToStructPtr (0.00s)
        mergo_test.go:31: Test failed:
                got  :
                 dst["a"] = &mergo_test.Struct{Value:""}

                want :
                 dst["a"] = &mergo_test.Struct{Value:"1"}

=== RUN TestMapToStruct
--- FAIL: TestMapToStruct (0.00s)
        mergo_test.go:50: Test failed:
                got  :
                 dst["a"] = mergo_test.Struct{Value:""}

                want :
                 dst["a"] = mergo_test.Struct{Value:"1"}

=== RUN TestStruct
--- PASS: TestStruct (0.00s)
=== RUN TestStructOfStruct
--- PASS: TestStructOfStruct (0.00s)
FAIL
exit status 1
FAIL    command-line-arguments  0.118s

It seems to work the way I expected for struct and struct of struct though.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions