Skip to content

Commit

Permalink
#### Version 0.7.2
Browse files Browse the repository at this point in the history
* New Feature: MapperSlice support ptr and struct
* New Feature: MapperMapSlice support ptr and struct
* Detail:
  - now support two slice's element type is ptr or struct in MapperSlice
  - now support slice's element type is ptr or struct in MapperMapSlice
  - About MapperMapSlice:
  ```golang
    //view test code in mapper_test.go:Test_MapperSlice\Test_MapperStructSlice
    //type ptr
    var toSlice []*testStruct
    //type struct
    var toSlice []testStruct
  ```
  - About MapperSlice:
  ```golang
    //view test code in mapper_test.go:Test_MapperMapSlice\Test_MapperStructMapSlice
    //type ptr
    var fromSlice []*FromStruct
 	var toSlice []*ToStruct
    //type struct
    var fromSlice []FromStruct
    var toSlice []ToStruct
  ```
* 2019-11-03 16:00 in ShangHai
  • Loading branch information
devfeel committed Nov 3, 2019
1 parent 405b6c9 commit 1737995
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 41 deletions.
95 changes: 54 additions & 41 deletions mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ func Register(obj interface{}) error {
if objValue == ZeroValue {
return errors.New("no exists this value")
}

return registerValue(objValue.Elem())
return registerValue(objValue)
}

// registerValue register Value to init Map
Expand Down Expand Up @@ -168,7 +167,12 @@ func GetFieldName(objElem reflect.Value, index int) string {
// 5.reflect.Float32\64
// 6.time.Time
func MapperMap(fromMap map[string]interface{}, toObj interface{}) error {
toElem := reflect.ValueOf(toObj).Elem()
toElemType := reflect.ValueOf(toObj)
toElem := toElemType
if toElemType.Kind() == reflect.Ptr {
toElem = toElemType.Elem()
}

if toElem == ZeroValue {
return errors.New("to obj is not legal value")
}
Expand Down Expand Up @@ -196,7 +200,7 @@ func MapperMap(fromMap map[string]interface{}, toObj interface{}) error {
}

// MapperMapSlice mapper from map[string]map[string]interface{} to a slice of any type's ptr
// toSlice must be a slice of any type's ptr.
// toSlice must be a slice of any type.
func MapperMapSlice(fromMaps map[string]map[string]interface{}, toSlice interface{}) error {
var err error
toValue := reflect.ValueOf(toSlice)
Expand All @@ -208,16 +212,57 @@ func MapperMapSlice(fromMaps map[string]map[string]interface{}, toSlice interfac
}

toElemType := reflect.TypeOf(toSlice).Elem().Elem()
if toElemType.Kind() != reflect.Ptr {
return errors.New("slice elem must ptr ")
}

realType := toElemType.Kind()
direct := reflect.Indirect(toValue)
//3 elem parse: 1.[]*type 2.*type 3.type
toElemType = toElemType.Elem()
if realType == reflect.Ptr {
toElemType = toElemType.Elem()
}
for _, v := range fromMaps {
elem := reflect.New(toElemType)
err = MapperMap(v, elem.Interface())
if err == nil {
if realType == reflect.Ptr {
direct.Set(reflect.Append(direct, elem))
} else {
direct.Set(reflect.Append(direct, elem.Elem()))
}
}
}
return err
}

// MapperSlice mapper from slice of struct to a slice of any type
// fromSlice and toSlice must be a slice of any type.
func MapperSlice(fromSlice, toSlice interface{}) error {
var err error
toValue := reflect.ValueOf(toSlice)
if toValue.Kind() != reflect.Ptr {
return errors.New("toSlice must pointer of slice")
}
if toValue.IsNil() {
return errors.New("toSlice must not nil pointer")
}

elemType := reflect.TypeOf(toSlice).Elem().Elem()
realType := elemType.Kind()
direct := reflect.Indirect(toValue)
//3 elem parse: 1.[]*type 2.*type 3.type
if realType == reflect.Ptr {
elemType = elemType.Elem()
}

fromElems := convertToSlice(fromSlice)
for _, v := range fromElems {
elem := reflect.New(elemType).Elem()
if realType == reflect.Ptr {
elem = reflect.New(elemType)
}
if realType == reflect.Ptr {
err = elemMapper(reflect.ValueOf(v).Elem(), elem.Elem())
} else {
err = elemMapper(reflect.ValueOf(v), elem)
}
if err == nil {
direct.Set(reflect.Append(direct, elem))
}
Expand Down Expand Up @@ -254,38 +299,6 @@ func Mapper(fromObj, toObj interface{}) error {
return elemMapper(fromElem, toElem)
}

// MapperSlice mapper from slice of struct to a slice of any type
// fromSlice and toSlice must be a slice of any type.
func MapperSlice(fromSlice, toSlice interface{}) error {
var err error
toValue := reflect.ValueOf(toSlice)
if toValue.Kind() != reflect.Ptr {
return errors.New("toSlice must pointer of slice")
}
if toValue.IsNil() {
return errors.New("toSlice must not nil pointer")
}

elemType := reflect.TypeOf(toSlice).Elem().Elem()
if elemType.Kind() != reflect.Ptr {
return errors.New("slice elem must ptr ")
}

direct := reflect.Indirect(toValue)
//3 elem parse: 1.[]*type 2.*type 3.type
elemType = elemType.Elem()

fromElems := convertToSlice(fromSlice)
for _, v := range fromElems {
elem := reflect.New(elemType)
err = elemMapper(reflect.ValueOf(v).Elem(), elem.Elem())
if err == nil {
direct.Set(reflect.Append(direct, elem))
}
}
return err
}

// Mapper mapper and set value from struct fromObj to toObj
// support auto register struct
func AutoMapper(fromObj, toObj interface{}) error {
Expand Down
36 changes: 36 additions & 0 deletions mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ func Test_MapperSlice(t *testing.T) {
}
}

func Test_MapperStructSlice(t *testing.T) {
SetEnabledTypeChecking(true)
var fromSlice []FromStruct
var toSlice []ToStruct
for i := 0; i < 10; i++ {
fromSlice = append(fromSlice, FromStruct{Name: "From" + strconv.Itoa(i), Sex: true, AA: "AA" + strconv.Itoa(i)})
}
err := MapperSlice(fromSlice, &toSlice)
if err != nil {
t.Error(err)
} else {
t.Log(toSlice, len(toSlice))
for _, v := range toSlice {
fmt.Println(v)
}
}
}

func BenchmarkMapperSlice(b *testing.B) {
var fromSlice []*FromStruct
var toSlice []*ToStruct
Expand Down Expand Up @@ -182,6 +200,24 @@ func Test_MapperMapSlice(t *testing.T) {
} else {
t.Log(toSlice, len(toSlice))
}
}

func Test_MapperStructMapSlice(t *testing.T) {
var toSlice []testStruct
fromMaps := make(map[string]map[string]interface{})
for i := 0; i < 10; i++ {
fromMap := make(map[string]interface{})
fromMap["Name"] = "s" + strconv.Itoa(i)
fromMap["Sex"] = true
fromMap["Age"] = i
fromMaps[strconv.Itoa(i)] = fromMap
}
err := MapperMapSlice(fromMaps, &toSlice)
if err != nil {
t.Error(err)
} else {
t.Log(toSlice, len(toSlice))
}

}

Expand Down
26 changes: 26 additions & 0 deletions version.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
## devfeel/mapper

#### Version 0.7.2
* New Feature: MapperSlice support ptr and struct
* New Feature: MapperMapSlice support ptr and struct
* Detail:
- now support two slice's element type is ptr or struct in MapperSlice
- now support slice's element type is ptr or struct in MapperMapSlice
- About MapperMapSlice:
```golang
//view test code in mapper_test.go:Test_MapperSlice\Test_MapperStructSlice
//type ptr
var toSlice []*testStruct
//type struct
var toSlice []testStruct
```
- About MapperSlice:
```golang
//view test code in mapper_test.go:Test_MapperMapSlice\Test_MapperStructMapSlice
//type ptr
var fromSlice []*FromStruct
var toSlice []*ToStruct
//type struct
var fromSlice []FromStruct
var toSlice []ToStruct
```
* 2019-11-03 16:00 in ShangHai

#### Version 0.7.1
* New Feature: Add TypeWrapper used to register custom Type Checker
* New Feature: Add UseWrapper used to add your TypeWrapper
Expand Down

0 comments on commit 1737995

Please sign in to comment.