Skip to content

Commit

Permalink
#### Version 0.7.1
Browse files Browse the repository at this point in the history
* New Feature: Add TypeWrapper used to register custom Type Checker
* New Feature: Add UseWrapper used to add your TypeWrapper
* Update: remove isTimeField, add TimeWrapper
* Detail:
  - now only support IsType used to check type
* 2019-02-03 16:00
  • Loading branch information
devfeel committed Feb 3, 2019
1 parent 87cb4fc commit 9b6a91f
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 16 deletions.
1 change: 1 addition & 0 deletions example/structfield/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func main() {

from2 := &ProductBasic{}
mapper.Mapper(to, from2)
fmt.Println(from)
fmt.Println(to)
fmt.Println(from2)
}
50 changes: 50 additions & 0 deletions example/typewrapper/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package main

import (
"fmt"
"github.com/devfeel/mapper"
"reflect"
"time"
)

type (
User struct {
Name string
Age int
Score decimal
Time time.Time
}

Student struct {
Name string
Age int
Score decimal
Time int64
}
)

type decimal struct {
value float32
}

type DecimalWrapper struct {
mapper.BaseTypeWrapper
}

func (w *DecimalWrapper) IsType(value reflect.Value) bool {
if _, ok := value.Interface().(decimal); ok {
return true
}
return false
}

func main() {
mapper.UseWrapper(&DecimalWrapper{})
user := &User{Name: "test", Age: 10, Score: decimal{value: 1}, Time: time.Now()}
stu := &Student{}

mapper.AutoMapper(user, stu)

fmt.Println(user)
fmt.Println(stu)
}
42 changes: 28 additions & 14 deletions mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import (

var (
ZeroValue reflect.Value
DefaultTimeWrapper *TimeWrapper
fieldNameMap sync.Map
registerMap sync.Map
enabledTypeChecking bool
enabledMapperStructField bool
enabledAutoTypeConvert bool
timeType = reflect.TypeOf(time.Now())
jsonTimeType = reflect.TypeOf(JSONTime(time.Now()))
typeWrappers []TypeWrapper
)

const (
Expand All @@ -34,6 +36,10 @@ const (

func init() {
ZeroValue = reflect.Value{}
DefaultTimeWrapper = NewTimeWrapper()
typeWrappers = []TypeWrapper{}
UseWrapper(DefaultTimeWrapper)

enabledTypeChecking = false
enabledMapperStructField = true
enabledAutoTypeConvert = true
Expand All @@ -43,6 +49,24 @@ func PackageVersion() string {
return packageVersion
}

// UseWrapper register a type wrapper
func UseWrapper(w TypeWrapper) {
if len(typeWrappers) > 0 {
typeWrappers[len(typeWrappers)-1].SetNext(w)
}
typeWrappers = append(typeWrappers, w)
}

// CheckIsTypeWrapper check value is in type wrappers
func CheckIsTypeWrapper(value reflect.Value) bool {
for _, w := range typeWrappers {
if w.IsType(value) {
return true
}
}
return false
}

// SetEnabledTypeChecking set enabled flag for TypeChecking
// if set true, the field type will be checked for consistency during mapping
// default is false
Expand Down Expand Up @@ -298,7 +322,7 @@ func elemMapper(fromElem, toElem reflect.Value) error {
if enabledMapperStructField &&
toFieldInfo.Kind() == reflect.Struct && fromFieldInfo.Kind() == reflect.Struct &&
toFieldInfo.Type() != fromFieldInfo.Type() &&
!isTimeField(toFieldInfo) && !isTimeField(fromFieldInfo) {
!CheckIsTypeWrapper(toFieldInfo) && !CheckIsTypeWrapper(fromFieldInfo) {
x := reflect.New(toFieldInfo.Type()).Elem()
err := elemMapper(fromFieldInfo, x)
if err != nil {
Expand All @@ -309,11 +333,11 @@ func elemMapper(fromElem, toElem reflect.Value) error {
} else {
isSet := false
if enabledAutoTypeConvert {
if isTimeField(fromFieldInfo) && toFieldInfo.Kind() == reflect.Int64 {
if DefaultTimeWrapper.IsType(fromFieldInfo) && toFieldInfo.Kind() == reflect.Int64 {
fromTime := fromFieldInfo.Interface().(time.Time)
toFieldInfo.Set(reflect.ValueOf(TimeToUnix(fromTime)))
isSet = true
} else if isTimeField(toFieldInfo) && fromFieldInfo.Kind() == reflect.Int64 {
} else if DefaultTimeWrapper.IsType(toFieldInfo) && fromFieldInfo.Kind() == reflect.Int64 {
fromTime := fromFieldInfo.Interface().(int64)
toFieldInfo.Set(reflect.ValueOf(UnixToTime(fromTime)))
isSet = true
Expand Down Expand Up @@ -392,7 +416,7 @@ func setFieldValue(fieldValue reflect.Value, fieldKind reflect.Kind, value inter
case reflect.Struct:
if value == nil {
fieldValue.Set(reflect.Zero(fieldValue.Type()))
} else if isTimeField(fieldValue) {
} else if DefaultTimeWrapper.IsType(fieldValue) {
var timeString string
if fieldValue.Type() == timeType {
timeString = ""
Expand Down Expand Up @@ -445,16 +469,6 @@ func setFieldValue(fieldValue reflect.Value, fieldKind reflect.Kind, value inter
return nil
}

func isTimeField(fieldValue reflect.Value) bool {
if _, ok := fieldValue.Interface().(time.Time); ok {
return true
}
if _, ok := fieldValue.Interface().(JSONTime); ok {
return true
}
return false
}

func getStructTag(field reflect.StructField) string {
tagValue := ""
//1.check mapperTagKey
Expand Down
4 changes: 2 additions & 2 deletions mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,15 @@ func Test_MapperMapSlice(t *testing.T) {

func Test_IsTimeField(t *testing.T) {
t1 := time.Now()
if isTimeField(reflect.ValueOf(t1)) {
if DefaultTimeWrapper.IsType(reflect.ValueOf(t1)) {
t.Log("check time.Now ok")
} else {
t.Error("check time.Now error")
}

var t2 JSONTime
t2 = JSONTime(time.Now())
if isTimeField(reflect.ValueOf(t2)) {
if DefaultTimeWrapper.IsType(reflect.ValueOf(t2)) {
t.Log("check mapper.Time ok")
} else {
t.Error("check mapper.Time error")
Expand Down
8 changes: 8 additions & 0 deletions version.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## devfeel/mapper

#### Version 0.7.1
* New Feature: Add TypeWrapper used to register custom Type Checker
* New Feature: Add UseWrapper used to add your TypeWrapper
* Update: remove isTimeField, add TimeWrapper
* Detail:
- now only support IsType used to check type
* 2019-02-03 16:00

#### Version 0.7
* New Feature: Add TimeToUnix\UnixToTime\TimeToUnixLocation\UnixToTimeLocation used to transform Time and Unix
* New Feature: Add SetEnabledAutoTypeConvert used to set whether or not auto do type convert when field is Time and Unix
Expand Down
37 changes: 37 additions & 0 deletions wrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mapper

import (
"reflect"
"time"
)

type TypeWrapper interface {
IsType(value reflect.Value) bool
SetNext(m TypeWrapper)
}

type BaseTypeWrapper struct {
next TypeWrapper
}

func (bm *BaseTypeWrapper) SetNext(m TypeWrapper) {
bm.next = m
}

type TimeWrapper struct {
BaseTypeWrapper
}

func (w *TimeWrapper) IsType(value reflect.Value) bool {
if _, ok := value.Interface().(time.Time); ok {
return true
}
if _, ok := value.Interface().(JSONTime); ok {
return true
}
return false
}

func NewTimeWrapper() *TimeWrapper {
return &TimeWrapper{}
}

0 comments on commit 9b6a91f

Please sign in to comment.