Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added registration for conversion function to different type #90

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

tomtwinkle
Copy link
Contributor

@tomtwinkle tomtwinkle commented Mar 5, 2021

Changed so that you can add a function that can be converted to any type.

Can freely customize the type conversion by defining the function for TypeCopier by the user.

type TypePair struct {
	SrcType reflect.Type
	DstType reflect.Type
}

type TypedCopier interface {
	// Define the conversion process
	Copy(dstValue, srcValue reflect.Value) error
	// Defines the type of the source field and the type of the destination field
	Pairs() []TypePair
}

Example

type timeToStringCopier struct{}

func (t timeToStringCopier) Pairs() []copier.TypePair {
	return []copier.TypePair{
		{
			SrcType: reflect.TypeOf(time.Time{}),
			DstType: reflect.TypeOf(""),
		},
		{
			SrcType: reflect.TypeOf(&time.Time{}),
			DstType: reflect.TypeOf(""),
		},
	}
}

func (t timeToStringCopier) Copy(dst, src reflect.Value) error {
	const timeFormat = "2006-01-02T15:04:05.999999999Z07:00"
	if src.Kind() == reflect.Ptr && src.IsNil() {
		if dst.Kind() == reflect.Ptr {
			dst.Set(reflect.Zero(reflect.TypeOf("")))
		}
		return nil
	}

	var val string
	if src.Kind() == reflect.Ptr {
		s, ok := src.Interface().(*time.Time)
		if !ok {
			return errors.New("type not match")
		}
		val = s.Format(timeFormat)
	} else {
		s, ok := src.Interface().(time.Time)
		if !ok {
			return errors.New("type not match")
		}
		val = s.Format(timeFormat)
	}
	dst.Set(reflect.ValueOf(val))
	return nil
}

func main() {
	type SrcStruct1 struct {
		Field1 time.Time
		Field2 *time.Time
	}

	type DestStruct1 struct {
		Field1 string
		Field2 string
	}

	c := copier.NewCopier()
	c.Register(&timeToStringCopier{})

	testTime := time.Date(2021, 3, 5, 1, 30, 0, 123000000, time.UTC)
	src := SrcStruct1{
		Field1: testTime,
		Field2: &testTime,
	}
	var dst DestStruct1

	if err := c.Copy(&dst, src); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%#v", dst)
	// DestStruct1{Field1:"2021-03-05T01:30:00.123Z", Field2:"2021-03-05T01:30:00.123Z"}
}

@jinzhu
Copy link
Owner

jinzhu commented May 31, 2021

Hello @tomtwinkle

Thank you for your PR, but maybe should pass those registered type in the Option struct? Also might be good to allow to register some default global converters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants