diff --git a/copier.go b/copier.go index b797156..e4c5dc6 100644 --- a/copier.go +++ b/copier.go @@ -37,9 +37,10 @@ const ( type Option struct { // setting this value to true will ignore copying zero values of all the fields, including bools, as well as a // struct having all it's fields set to their zero values respectively (see IsZero() in reflect/value.go) - IgnoreEmpty bool - DeepCopy bool - Converters []TypeConverter + IgnoreEmpty bool + CaseSensitive bool + DeepCopy bool + Converters []TypeConverter } func (opt Option) converters() map[converterPair]TypeConverter { @@ -328,7 +329,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) break } - toField := dest.FieldByName(destFieldName) + toField := fieldByName(dest, destFieldName, opt.CaseSensitive) if toField.IsValid() { if toField.CanSet() { isSet, err := set(toField, fromField, opt.DeepCopy, converters) @@ -374,7 +375,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) } if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 && !shouldIgnore(fromMethod, opt.IgnoreEmpty) { - if toField := dest.FieldByName(destFieldName); toField.IsValid() && toField.CanSet() { + if toField := fieldByName(dest, destFieldName, opt.CaseSensitive); toField.IsValid() && toField.CanSet() { values := fromMethod.Call([]reflect.Value{}) if len(values) >= 1 { set(toField, values[0], opt.DeepCopy, converters) @@ -769,3 +770,11 @@ func driverValuer(v reflect.Value) (i driver.Valuer, ok bool) { i, ok = v.Addr().Interface().(driver.Valuer) return } + +func fieldByName(v reflect.Value, name string, caseSensitive bool) reflect.Value { + if caseSensitive { + return v.FieldByName(name) + } + + return v.FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, name) }) +} diff --git a/copier_benchmark_test.go b/copier_benchmark_test.go index a9a25d8..d9daccc 100644 --- a/copier_benchmark_test.go +++ b/copier_benchmark_test.go @@ -29,7 +29,7 @@ func BenchmarkNamaCopy(b *testing.B) { for x := 0; x < b.N; x++ { employee := &Employee{ Name: user.Name, - Nickname: &user.Nickname, + NickName: &user.Nickname, Age: int64(user.Age), FakeAge: int(*user.FakeAge), DoubleAge: user.DoubleAge(), diff --git a/copier_test.go b/copier_test.go index de8dff8..4769eba 100644 --- a/copier_test.go +++ b/copier_test.go @@ -30,7 +30,7 @@ type Employee struct { _User *User Name string Birthday *time.Time - Nickname *string + NickName *string Age int64 FakeAge int EmployeID int64 @@ -48,7 +48,7 @@ func checkEmployee(employee Employee, user User, t *testing.T, testCase string) if employee.Name != user.Name { t.Errorf("%v: Name haven't been copied correctly.", testCase) } - if employee.Nickname == nil || *employee.Nickname != user.Nickname { + if employee.NickName == nil || *employee.NickName != user.Nickname { t.Errorf("%v: NickName haven't been copied correctly.", testCase) } if employee.Birthday == nil && user.Birthday != nil { @@ -102,7 +102,7 @@ func TestCopySameStructWithPointerField(t *testing.T) { func checkEmployee2(employee Employee, user *User, t *testing.T, testCase string) { if user == nil { - if employee.Name != "" || employee.Nickname != nil || employee.Birthday != nil || employee.Age != 0 || + if employee.Name != "" || employee.NickName != nil || employee.Birthday != nil || employee.Age != 0 || employee.DoubleAge != 0 || employee.FakeAge != 0 || employee.SuperRule != "" || employee.Notes != nil { t.Errorf("%v : employee should be empty", testCase) }