jinzhu / copier

Copier for golang, copy value from struct to struct and more
MIT License
5.57k stars 489 forks source link

Valuer interface #191

Open System-Glitch opened 1 year ago

System-Glitch commented 1 year ago

This PR adds support for a new copier.Valuer interface. This interface lets custom types implement a function returning the actual value to copy.

For example if your type is a wrapper, or if it doesn't have to implement sql/driver.Valuer, you can implement this interface so the returned value will be used instead. It can also be used to format your type or convert it to another one before being copied.
It differs from TypeConverter in several ways:

It works in a very simple way: at the start of copier() and set() functions, if the from value implements Valuer,it is replaced with the one returned by CopyValue(), and the usual process continues.

Example use-case:

The Undefined type allows to know if a field in a structure is undefined (which is different from nil, in the case of nullable values). This is useful for PATCH updates so we just omit the fields that are not present.

type Undefined[T any] struct {
    Val     T
    Present bool
}

func (u Undefined[T]) CopyValue() any {
    if !u.Present {
        return nil
    }

    if valuer, ok := any(&u.Val).(copier.Valuer); ok {
        return valuer.CopyValue()
    }
    return u.Val
}

If the field is not present, the struct has its zero-value, which is handy so it can be ignored with the option IgnoreEmpty.


System-Glitch commented 1 year ago

For those wanting this feature, I decided to maintain a fork: https://github.com/go-goyave/copier

Contributions are also welcome there.

It also includes a few other bug fixes, including #182 #185