Compare commits
	
		
			4 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 09f4cfc59a | |||
| dea7cb49b0 | |||
| bf847e845e | |||
| 41412ed76e | 
| @ -1,5 +1,5 @@ | ||||
| [](https://goreportcard.com/report/github.com/go-convert/fields) | ||||
| [](https://github.com/go-convert/fields/actions) | ||||
| [](https://goreportcard.com/report/git.webz.asia/go-convert/fields) | ||||
| [](https://git.webz.asia/go-convert/fields/actions) | ||||
| [](https://travis-ci.org/go-convert/fields) | ||||
| [](https://codecov.io/gh/go-convert/fields) | ||||
| 
 | ||||
| @ -15,7 +15,7 @@ import ( | ||||
| 	"log" | ||||
| 	"encoding/json" | ||||
| 
 | ||||
| 	"github.com/go-convert/fields" | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type FromStruct struct { | ||||
| @ -80,7 +80,7 @@ import ( | ||||
| 	"log" | ||||
| 	"encoding/json" | ||||
| 
 | ||||
| 	"github.com/go-convert/fields" | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type FromStructCustom struct { | ||||
|  | ||||
| @ -25,7 +25,7 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"github.com/go-convert/fields" | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type fromStruct struct { | ||||
|  | ||||
| @ -25,7 +25,7 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"github.com/go-convert/fields" | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type fromStructCustom struct { | ||||
|  | ||||
							
								
								
									
										75
									
								
								examples/example-3/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								examples/example-3/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| /* | ||||
|  * Copyright (c) 2020 Alex aka mailoman <alex@webz.asia> | ||||
|  * | ||||
|  *  Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  *  you may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  *  Unless required by applicable law or agreed to in writing, software | ||||
|  *  distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  *  See the License for the specific language governing permissions and | ||||
|  *  limitations under the License. | ||||
|  * | ||||
|  *   @author Alex aka mailoman <alex@webz.asia> | ||||
|  *   @copyright Copyright (c) 2020 Alex aka mailoman <alex@webz.asia> | ||||
|  *   @since 26.01.2020 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type FromStructBase struct { | ||||
| 	ID     string `conv:"new,update"` | ||||
| 	Field1 string `conv:"new,update"` | ||||
| } | ||||
| 
 | ||||
| type fromStruct struct { | ||||
| 	FromStructBase `conv:"new,update"` | ||||
| 	Field2         string `conv:"update"` | ||||
| } | ||||
| 
 | ||||
| type toStruct struct { | ||||
| 	ID     string | ||||
| 	Field1 string | ||||
| 	Field2 string | ||||
| 	Field3 string | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	fromDefault := fromStruct{ | ||||
| 		FromStructBase{"1", "field 1 value"}, "field 2 value", | ||||
| 	} | ||||
| 	toDefault := toStruct{ | ||||
| 		"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", | ||||
| 	} | ||||
| 
 | ||||
| 	log.Print("example 3.1 - new") | ||||
| 	from := fromDefault | ||||
| 	to := toDefault | ||||
| 
 | ||||
| 	fields.Сonvert(from, "new", &to) | ||||
| 	fromB, _ := json.Marshal(from) | ||||
| 	toB, _ := json.Marshal(to) | ||||
| 
 | ||||
| 	log.Printf("from %s => to %s", string(fromB), string(toB)) | ||||
| 
 | ||||
| 	log.Print("example 3.2 - update") | ||||
| 	from = fromDefault | ||||
| 	to = toDefault | ||||
| 
 | ||||
| 	fields.Сonvert(from, "update", &to) | ||||
| 	fromB, _ = json.Marshal(from) | ||||
| 	toB, _ = json.Marshal(to) | ||||
| 
 | ||||
| 	log.Printf("from %s => to %s", string(fromB), string(toB)) | ||||
| } | ||||
							
								
								
									
										76
									
								
								examples/example-4/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								examples/example-4/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| /* | ||||
|  * Copyright (c) 2020 Alex aka mailoman <alex@webz.asia> | ||||
|  * | ||||
|  *  Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  *  you may not use this file except in compliance with the License. | ||||
|  *  You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  *  Unless required by applicable law or agreed to in writing, software | ||||
|  *  distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  *  See the License for the specific language governing permissions and | ||||
|  *  limitations under the License. | ||||
|  * | ||||
|  *   @author Alex aka mailoman <alex@webz.asia> | ||||
|  *   @copyright Copyright (c) 2020 Alex aka mailoman <alex@webz.asia> | ||||
|  *   @since 26.01.2020 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"log" | ||||
| 
 | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| 	"github.com/satori/go.uuid" | ||||
| ) | ||||
| 
 | ||||
| type FromStructBase struct { | ||||
| 	ID     uuid.UUID `conv:"new,update"` | ||||
| 	Field1 string    `conv:"new,update"` | ||||
| } | ||||
| 
 | ||||
| type fromStruct struct { | ||||
| 	FromStructBase `conv:"new,update"` | ||||
| 	Field2         string `conv:"update"` | ||||
| } | ||||
| 
 | ||||
| type toStruct struct { | ||||
| 	Id     string | ||||
| 	Field1 string | ||||
| 	Field2 string | ||||
| 	Field3 string | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	fromDefault := fromStruct{ | ||||
| 		FromStructBase{uuid.FromStringOrNil("bb9f2a39-1dbd-4929-8e87-4863696d9cb3"), "field 1 value"}, "field 2 value", | ||||
| 	} | ||||
| 	toDefault := toStruct{ | ||||
| 		"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", | ||||
| 	} | ||||
| 
 | ||||
| 	log.Print("example 4.1 - new") | ||||
| 	from := fromDefault | ||||
| 	to := toDefault | ||||
| 
 | ||||
| 	fields.Сonvert(from, "new", &to) | ||||
| 	fromB, _ := json.Marshal(from) | ||||
| 	toB, _ := json.Marshal(to) | ||||
| 
 | ||||
| 	log.Printf("from %s => to %s", string(fromB), string(toB)) | ||||
| 
 | ||||
| 	log.Print("example 4.2 - update") | ||||
| 	from = fromDefault | ||||
| 	to = toDefault | ||||
| 
 | ||||
| 	fields.Сonvert(from, "update", &to) | ||||
| 	fromB, _ = json.Marshal(from) | ||||
| 	toB, _ = json.Marshal(to) | ||||
| 
 | ||||
| 	log.Printf("from %s => to %s", string(fromB), string(toB)) | ||||
| } | ||||
							
								
								
									
										27
									
								
								fields.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								fields.go
									
									
									
									
									
								
							| @ -25,6 +25,8 @@ import ( | ||||
| 	"log" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/satori/go.uuid" | ||||
| ) | ||||
| 
 | ||||
| //Convert copies field values from one struct to another based on tags setup
 | ||||
| @ -54,7 +56,7 @@ func Сonvert(from interface{}, kind string, to interface{}) { | ||||
| 		// skip unexported fields. from godoc:
 | ||||
| 		// PkgPath is the package path that qualifies a lower case (unexported)
 | ||||
| 		// field name. It is empty for upper case (exported) field names.
 | ||||
| 		if f.PkgPath != "" { | ||||
| 		if f.PkgPath != "" && f.Name == "" { | ||||
| 			continue | ||||
| 		} | ||||
| 		fv := v.Field(i) | ||||
| @ -70,7 +72,28 @@ func Сonvert(from interface{}, kind string, to interface{}) { | ||||
| 
 | ||||
| 		if found { | ||||
| 			ft := vt.FieldByName(f.Name) | ||||
| 			ft.Set(fv) | ||||
| 			if f.Name == strings.ToUpper(f.Name) && !ft.IsValid() { | ||||
| 				// was uppercase and not valid => to Capitalize first letter
 | ||||
| 				ft = vt.FieldByName(strings.Title(strings.ToLower(f.Name))) | ||||
| 			} | ||||
| 
 | ||||
| 			if !ft.IsValid() && fv.Kind() == reflect.Struct { | ||||
| 				Сonvert(fv.Interface(), kind, to) | ||||
| 			} else { | ||||
| 				if ft.IsValid() { | ||||
| 					switch f.Type.String() { | ||||
| 					case "uuid.UUID": | ||||
| 						mv := fv.Interface().(uuid.UUID) | ||||
| 						if ft.Type().String() == "uuid.UUID" { | ||||
| 							ft.Set(fv) | ||||
| 						} else { | ||||
| 							ft.SetString(mv.String()) | ||||
| 						} | ||||
| 					default: | ||||
| 						ft.Set(fv) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										185
									
								
								fields_test.go
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								fields_test.go
									
									
									
									
									
								
							| @ -24,9 +24,10 @@ package fields_test | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/satori/go.uuid" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 
 | ||||
| 	"github.com/go-convert/fields" | ||||
| 	"git.webz.asia/go-convert/fields" | ||||
| ) | ||||
| 
 | ||||
| type FromStruct struct { | ||||
| @ -51,6 +52,14 @@ type ToStruct struct { | ||||
| 	Field4 string | ||||
| } | ||||
| 
 | ||||
| type ToStruct2 struct { | ||||
| 	Id     string | ||||
| 	Field1 string | ||||
| 	Field2 string | ||||
| 	Field3 string | ||||
| 	Field4 string | ||||
| } | ||||
| 
 | ||||
| type FromStructCustom struct { | ||||
| 	ID     string `copy:"new,update"` | ||||
| 	Field1 string `copy:"new,update"` | ||||
| @ -59,6 +68,30 @@ type FromStructCustom struct { | ||||
| 	Field4 string `copy:"category-1,noempty"` | ||||
| } | ||||
| 
 | ||||
| type FromStructBase struct { | ||||
| 	ID     string `conv:"new,update"` | ||||
| 	Field1 string `conv:"new,update"` | ||||
| } | ||||
| 
 | ||||
| type FromStructExtraBase struct { | ||||
| 	ID     uuid.UUID `conv:"new,update"` | ||||
| 	Field1 string    `conv:"new,update"` | ||||
| } | ||||
| 
 | ||||
| type FromStructCombined struct { | ||||
| 	FromStructBase `conv:"new,update"` | ||||
| 	Field2         string `conv:"update"` | ||||
| 	Field3         string `conv:"update,omit"` | ||||
| 	Field4         string `conv:"category-1,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type FromStructCombinedExtra struct { | ||||
| 	FromStructExtraBase `conv:"new,update"` | ||||
| 	Field2              uuid.UUID `conv:"update"` | ||||
| 	Field3              string    `conv:"update,omit"` | ||||
| 	Field4              string    `conv:"category-1,omitempty"` | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	// testsNormal provides normal test cases
 | ||||
| 	testsNormal = []struct { | ||||
| @ -258,6 +291,128 @@ var ( | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	// testsCombinedNormal provides normal test cases with embedded structs
 | ||||
| 	testsCombinedNormal = []struct { | ||||
| 		from       FromStructCombined | ||||
| 		kind       string | ||||
| 		to         ToStruct | ||||
| 		expectedTo ToStruct | ||||
| 	}{ | ||||
| 		// case 3.1
 | ||||
| 		{ | ||||
| 			FromStructCombined{ | ||||
| 				FromStructBase{"1", "field 1 value"}, "field 2 value", "omitting", "", | ||||
| 			}, | ||||
| 			"new", | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 			ToStruct{ | ||||
| 				"1", "field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 3.2
 | ||||
| 		{ | ||||
| 			FromStructCombined{ | ||||
| 				FromStructBase{"1", "field 1 value"}, "field 2 value", "omitting", "", | ||||
| 			}, | ||||
| 			"update", | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 			ToStruct{ | ||||
| 				"1", "field 1 value", "field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 3.3.1
 | ||||
| 		{ | ||||
| 			FromStructCombined{ | ||||
| 				FromStructBase{"1", "field 1 value"}, "field 2 value", "omitting", "", | ||||
| 			}, | ||||
| 			"category-1", | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 3.3.2
 | ||||
| 		{ | ||||
| 			FromStructCombined{ | ||||
| 				FromStructBase{"1", "field 1 value"}, "field 2 value", "omitting", "not empty", | ||||
| 			}, | ||||
| 			"category-1", | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 			ToStruct{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "not empty", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	// testsCombinedExtra provides normal test cases with embedded structs with more features
 | ||||
| 	testsCombinedExtra = []struct { | ||||
| 		from       FromStructCombinedExtra | ||||
| 		kind       string | ||||
| 		to         ToStruct2 | ||||
| 		expectedTo ToStruct2 | ||||
| 	}{ | ||||
| 		// case 4.1
 | ||||
| 		{ | ||||
| 			FromStructCombinedExtra{ | ||||
| 				FromStructExtraBase{uuid.FromStringOrNil("bb9f2a39-1dbd-4929-8e87-4863696d9cb3"), "field 1 value"}, uuid.FromStringOrNil("d039089d-27f5-438b-8b70-90eb3df0d79b"), "omitting", "", | ||||
| 			}, | ||||
| 			"new", | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 			ToStruct2{ | ||||
| 				"bb9f2a39-1dbd-4929-8e87-4863696d9cb3", "field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 4.2
 | ||||
| 		{ | ||||
| 			FromStructCombinedExtra{ | ||||
| 				FromStructExtraBase{uuid.FromStringOrNil("bb9f2a39-1dbd-4929-8e87-4863696d9cb3"), "field 1 value"}, uuid.FromStringOrNil("d039089d-27f5-438b-8b70-90eb3df0d79b"), "omitting", "", | ||||
| 			}, | ||||
| 			"update", | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "", | ||||
| 			}, | ||||
| 			ToStruct2{ | ||||
| 				"bb9f2a39-1dbd-4929-8e87-4863696d9cb3", "field 1 value", "d039089d-27f5-438b-8b70-90eb3df0d79b", "old field 3 value", "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 4.3.1
 | ||||
| 		{ | ||||
| 			FromStructCombinedExtra{ | ||||
| 				FromStructExtraBase{uuid.FromStringOrNil("bb9f2a39-1dbd-4929-8e87-4863696d9cb3"), "field 1 value"}, uuid.FromStringOrNil("d039089d-27f5-438b-8b70-90eb3df0d79b"), "omitting", "", | ||||
| 			}, | ||||
| 			"category-1", | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 		}, | ||||
| 		// case 4.3.2
 | ||||
| 		{ | ||||
| 			FromStructCombinedExtra{ | ||||
| 				FromStructExtraBase{uuid.FromStringOrNil("bb9f2a39-1dbd-4929-8e87-4863696d9cb3"), "field 1 value"}, uuid.FromStringOrNil("d039089d-27f5-438b-8b70-90eb3df0d79b"), "omitting", "not empty", | ||||
| 			}, | ||||
| 			"category-1", | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "old field 4 value", | ||||
| 			}, | ||||
| 			ToStruct2{ | ||||
| 				"old val 1", "old field 1 value", "old field 2 value", "old field 3 value", "not empty", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func TestConvert_Normal(t *testing.T) { | ||||
| @ -357,3 +512,31 @@ func TestOmitEmptyTagName(t *testing.T) { | ||||
| 
 | ||||
| 	assert.Equal(t, newValue, fields.OmitEmptyTagName()) | ||||
| } | ||||
| 
 | ||||
| func TestConvert_CombinedNormal(t *testing.T) { | ||||
| 	fields.SetDefaults() | ||||
| 	for _, test := range testsCombinedNormal { | ||||
| 
 | ||||
| 		to := &ToStruct{} | ||||
| 		*to = test.to | ||||
| 
 | ||||
| 		fields.Сonvert(test.from, test.kind, to) | ||||
| 
 | ||||
| 		assert.NotEmpty(t, *to) | ||||
| 		assert.Equal(t, test.expectedTo, *to) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestConvert_CombinedExtra(t *testing.T) { | ||||
| 	fields.SetDefaults() | ||||
| 	for _, test := range testsCombinedExtra { | ||||
| 
 | ||||
| 		to := &ToStruct2{} | ||||
| 		*to = test.to | ||||
| 
 | ||||
| 		fields.Сonvert(test.from, test.kind, to) | ||||
| 
 | ||||
| 		assert.NotEmpty(t, *to) | ||||
| 		assert.Equal(t, test.expectedTo, *to) | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										7
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,5 +1,8 @@ | ||||
| module github.com/go-convert/fields | ||||
| module git.webz.asia/go-convert/fields | ||||
| 
 | ||||
| go 1.13 | ||||
| 
 | ||||
| require github.com/stretchr/testify v1.4.0 | ||||
| 		require ( | ||||
| 		github.com/satori/go.uuid v1.2.0 | ||||
| 		github.com/stretchr/testify v1.4.0 | ||||
| 		) | ||||
|  | ||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= | ||||
| github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user