diff icon indicating copy to clipboard operation
diff copied to clipboard

unsupported type: MongoDB primitive.ObjectID

Open hwebb opened this issue 4 years ago • 7 comments

Will there be a support for the type primitive.ObjectID for MongoDB? Or is there a way to add types ourselves? https://pkg.go.dev/go.mongodb.org/mongo-driver

Right now I have to deactivate all of them with diff:"-", that wouldn't cause an issue if I was only using primitive.ObjectID as main ID, but I'm also using that to link collections, so I need it in other area on the struct.

type ObjectID [12]byte

fmt.Print(reflect.ValueOf(obj.ID).Kind()) // array unsupported type: array

It seems that you support Slice only and not Array

Besides that, it works well. Thanks for this library!

hwebb avatar Apr 17 '21 16:04 hwebb

For one of my projects I have defined a custom value differ for ObjectIDs:

type objectIDDiffer struct{}

var (
	objectIDType = reflect.TypeOf(primitive.NilObjectID)
)

func (d objectIDDiffer) Match(a, b reflect.Value) bool {
	aok := a.Kind() == objectIDType.Kind() && a.Type() == objectIDType
	bok := b.Kind() == objectIDType.Kind() && b.Type() == objectIDType
	return aok && bok || a.Kind() == reflect.Invalid && bok || b.Kind() == reflect.Invalid && aok
}

func (d objectIDDiffer) Diff(cl *diff.Changelog, path []string, a, b reflect.Value) error {
	if a.Kind() == reflect.Invalid {
		cl.Add(diff.CREATE, path, nil, b.Interface())
		return nil
	}
	if b.Kind() == reflect.Invalid {
		cl.Add(diff.DELETE, path, a.Interface(), nil)
		return nil
	}
	av := a.Interface().(primitive.ObjectID)
	bv := b.Interface().(primitive.ObjectID)
	if av != bv {
		cl.Add(diff.UPDATE, path, av, bv)
	}
	return nil
}

func (d objectIDDiffer) InsertParentDiffer(dfunc func(path []string, a, b reflect.Value, p interface{}) error) {
}
differ, err = diff.NewDiffer(
	diff.CustomValueDiffers(objectIDDiffer{}),
)

hjr265 avatar Apr 18 '21 10:04 hjr265

Thank you @hjr265 , so you think that type will never be included in this library? Because MongoDB is increasingly popular.

hwebb avatar Apr 24 '21 15:04 hwebb

@hwebb That is up to the author of the package.

If it was me, I wouldn't add support for primitive.ObjectID. This package should be kept generic. Moreover, it already allows you to add custom differs for types that you need to support.

hjr265 avatar Apr 25 '21 08:04 hjr265

Hi @hwebb, thanks for raising the issue.

I pretty much agree with what @hjr265 said. Directly supporting types from external libraries is outside the scope of this project as it would result in imposing a larger set of dependencies on our users.

We may be able to resolve your issue by adding support for array, but thats not a guaranteed fix as there may be other types in primitive.ObjectID that are unsupported.

As @hjr265 suggested, you are probably best of making use of the CustomValueDiffers for now.

I will try and take a look at adding support for arrays, as that may be helpfulfor other usecases.

purehyperbole avatar Apr 25 '21 10:04 purehyperbole

Thanks @purehyperbole thanks for the explanation, obviously adding dependencies is not a good option. I'll stick to the code from @hjr265 for now. Thanks

hwebb avatar Apr 25 '21 12:04 hwebb

I had the same issue with my own struct that contains an array. As I was only using this library to debug something, I solved this by modifying my local vendored code of this library (I don't recommend doing this). I added

	case are(a, b, reflect.Array, reflect.Invalid):
		return d.diffSlice(path, a, b)

to this switch: https://github.com/r3labs/diff/blob/master/diff.go#L164

I'm posting this, because it seems to work correctly, and this may be all that's needed to support arrays. But I admit, I didn't delve much into the library's code, and the fix seems a bit too simple, so I'm probably missing something. That's why I didn't create a pull request.

peterfajdiga avatar Jul 18 '21 10:07 peterfajdiga