r3labs / diff

A library for diffing golang structures
Mozilla Public License 2.0
895 stars 84 forks source link

Changelog Serialization - Interface issue #92

Open tiger5226 opened 2 years ago

tiger5226 commented 2 years ago

Hi diff team,

I am working on a project that is leveraging the library and there appears to be a problem with interfaces when serializing the change logs. The types get lost in translation.

I have created a simplified reproduction of the issue at hand that exemplifies the issue. In the example there is a type that has a field which is an interface where we are adding different types that qualify for the interface. When we serialize the changelog, then de-serialize the changelog, then apply it as a patch, you will see the error. The important piece is that it does not recognize what type it was from before the change log was serialized.

type Something interface {
    Name() string
}
type A struct {
    First  string
    Second string
}

func (a A) Name() string {
    return a.First + a.Second
}

type B struct {
    First  string
    Second string
}

func (b B) Name() string {
    return b.First + b.Second
}

type Example struct {
    This []Something
}

func TestChangeExample(t *testing.T) {
    before := Example{This: []Something{A{First: "Joe", Second: "Shmo"}}}
    after := Example{This: []Something{A{First: "Joe", Second: "Shmo"}, B{First: "Jane", Second: "Doe"}}}
    differ, err := diff.NewDiffer(diff.ConvertCompatibleTypes())
    if err != nil {
        t.Fatal(err)
    }
    cl, err := differ.Diff(&before, &after)
    if err != nil {
        t.Fatal(err)
    }
    b, err := json.Marshal(&cl)
    if err != nil {
        t.Fatal(err)
    }
    var newCL diff.Changelog
    err = json.Unmarshal(b, &newCL)
    if err != nil {
        t.Fatal(err)
    }

    pl := diff.Patch(newCL, &before)
    for _, p := range pl {
        if p.Errors != nil {
            t.Fatal(p.Errors)
        }
    }
    println("success?")
}

In the Goland IDE inspection and comparison to the before after shows that it does not recognize the same type: image

zonewave commented 1 year ago

"Example.This" is a something interface . When apply changelog and supplement second element, it cannot determine which implementation type is