Skip to content

Commit 8360d9a

Browse files
committed
#### Version 0.7.13
* Feature: Added the "composite-field" tag to continue expanding and searching for corresponding field mappings when encountering composite fields in a Struct. Currently, only one level of expansion is supported. * Tips: Thanks to @naeemaei for issue #39 * For my birthday! * you can use like this: ``` go // Base model type BaseModel struct { Id int `json:"id"` } // Country model type Country struct { BaseModel `json:"composite-field"` Name string `json:"name"` } ``` * 2023-04-15 19:00 in ShangHai
1 parent f620136 commit 8360d9a

6 files changed

Lines changed: 116 additions & 86 deletions

File tree

constant.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package mapper
22

33
const (
4-
packageVersion = "0.7.12"
5-
mapperTagKey = "mapper"
6-
jsonTagKey = "json"
7-
IgnoreTagValue = "-"
8-
nameConnector = "_"
9-
formatTime = "15:04:05"
10-
formatDate = "2006-01-02"
11-
formatDateTime = "2006-01-02 15:04:05"
4+
packageVersion = "0.7.13"
5+
mapperTagKey = "mapper"
6+
jsonTagKey = "json"
7+
IgnoreTagValue = "-"
8+
CompositeFieldTagValue = "composite-field"
9+
nameConnector = "_"
10+
formatTime = "15:04:05"
11+
formatDate = "2006-01-02"
12+
formatDateTime = "2006-01-02 15:04:05"
1213
)

example/object/go.mod

Lines changed: 0 additions & 7 deletions
This file was deleted.

example/object/go.sum

Whitespace-only changes.

example/object/main.go

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,33 @@ import (
55
"github.com/devfeel/mapper"
66
)
77

8-
type (
9-
User struct {
10-
Name string `json:"name" mapper:"name"`
11-
Class int `mapper:"class"`
12-
Age int `json:"age" mapper:"-"`
13-
}
14-
15-
Student struct {
16-
Name string `json:"name" mapper:"name"`
17-
Class int `mapper:"class"`
18-
Age []int `json:"age" mapper:"-"`
19-
}
20-
)
21-
22-
func main() {
23-
user := &User{Name: "shyandsy", Class: 1, Age: 10}
24-
student := &Student{}
25-
26-
// create mapper object
27-
m := mapper.NewMapper()
28-
29-
// in the version < v0.7.8, we will use field name as key when mapping structs
30-
// we keep it as default behavior in this version
31-
m.SetEnableFieldIgnoreTag(true)
32-
33-
student.Age = []int{1}
8+
// Base model
9+
type BaseModel struct {
10+
Id int `json:"id"`
11+
NameX string
12+
}
3413

35-
// disable the json tag
36-
m.SetEnabledJsonTag(false)
14+
// Country model
15+
type Country struct {
16+
BaseModel `json:"composite-field"`
17+
Name string `json:"name"`
18+
}
3719

38-
// student::age should be 1
39-
m.Mapper(user, student)
20+
type CountryRes struct {
21+
Id int `json:"id"`
22+
Name string `json:"name"`
23+
}
4024

41-
fmt.Println("user:")
42-
fmt.Println(user)
43-
fmt.Println("student:")
44-
fmt.Println(student)
25+
func main() {
26+
var items *[]Country = new([]Country)
27+
c := &Country{BaseModel{1, "1X"}, "111"}
28+
*items = append(*items, *c)
29+
var mitems *[]CountryRes = new([]CountryRes)
30+
mapper.MapperSlice(items, mitems)
31+
fmt.Println(items)
32+
fmt.Println(mitems)
33+
34+
to := &CountryRes{}
35+
mapper.Mapper(c, to)
36+
fmt.Println(to)
4537
}

mapper_object_internal.go

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -93,58 +93,83 @@ func (dm *mapperObject) elemMapper(fromElem, toElem reflect.Value) error {
9393
return nil
9494
}
9595

96+
// elemToStruct to convert the different structs for assignment.
9697
func (dm *mapperObject) elemToStruct(fromElem, toElem reflect.Value) {
9798
for i := 0; i < fromElem.NumField(); i++ {
9899
fromFieldInfo := fromElem.Field(i)
99100
fieldName := dm.getFieldName(fromElem, i)
100101
if fieldName == IgnoreTagValue {
101102
continue
102103
}
103-
104-
// check field is exists
105-
realFieldName, exists := dm.CheckExistsField(toElem, fieldName)
106-
if !exists {
107-
continue
104+
if fieldName == CompositeFieldTagValue &&
105+
fromFieldInfo.Kind() == reflect.Struct {
106+
//If composite fields are identified, further decomposition and judgment will be taken.
107+
fromElem := fromFieldInfo
108+
for i := 0; i < fromElem.NumField(); i++ {
109+
fromFieldInfo := fromElem.Field(i)
110+
fieldName := dm.getFieldName(fromElem, i)
111+
if fieldName == IgnoreTagValue {
112+
continue
113+
}
114+
err := dm.convertstructfieldInternal(fieldName, fromFieldInfo, toElem)
115+
if err != nil {
116+
fmt.Println("auto mapper failed", fromFieldInfo, "error", err.Error())
117+
}
118+
}
119+
} else {
120+
err := dm.convertstructfieldInternal(fieldName, fromFieldInfo, toElem)
121+
if err != nil {
122+
fmt.Println("auto mapper failed", fromFieldInfo, "error", err.Error())
123+
}
108124
}
125+
}
126+
}
109127

110-
toFieldInfo := toElem.FieldByName(realFieldName)
111-
// check field is same type
112-
if dm.enabledTypeChecking {
113-
if fromFieldInfo.Kind() != toFieldInfo.Kind() {
114-
continue
115-
}
128+
// convertstructfieldInternal to convert the fields of different structs for assignment.
129+
func (dm *mapperObject) convertstructfieldInternal(fieldName string, fromFieldInfo, toElem reflect.Value) error {
130+
// check field is exists
131+
realFieldName, exists := dm.CheckExistsField(toElem, fieldName)
132+
if !exists {
133+
return nil
134+
}
135+
136+
toFieldInfo := toElem.FieldByName(realFieldName)
137+
// check field is same type
138+
if dm.enabledTypeChecking {
139+
if fromFieldInfo.Kind() != toFieldInfo.Kind() {
140+
return nil
116141
}
142+
}
117143

118-
if dm.enabledMapperStructField &&
119-
toFieldInfo.Kind() == reflect.Struct && fromFieldInfo.Kind() == reflect.Struct &&
120-
toFieldInfo.Type() != fromFieldInfo.Type() &&
121-
!dm.checkIsTypeWrapper(toFieldInfo) && !dm.checkIsTypeWrapper(fromFieldInfo) {
122-
x := reflect.New(toFieldInfo.Type()).Elem()
123-
err := dm.elemMapper(fromFieldInfo, x)
124-
if err != nil {
125-
fmt.Println("auto mapper failed", fromFieldInfo, "=>", toFieldInfo, "error", err.Error())
126-
} else {
127-
toFieldInfo.Set(x)
128-
}
144+
if dm.enabledMapperStructField &&
145+
toFieldInfo.Kind() == reflect.Struct && fromFieldInfo.Kind() == reflect.Struct &&
146+
toFieldInfo.Type() != fromFieldInfo.Type() &&
147+
!dm.checkIsTypeWrapper(toFieldInfo) && !dm.checkIsTypeWrapper(fromFieldInfo) {
148+
x := reflect.New(toFieldInfo.Type()).Elem()
149+
err := dm.elemMapper(fromFieldInfo, x)
150+
if err != nil {
151+
return err
129152
} else {
130-
isSet := false
131-
if dm.enabledAutoTypeConvert {
132-
if dm.DefaultTimeWrapper.IsType(fromFieldInfo) && toFieldInfo.Kind() == reflect.Int64 {
133-
fromTime := fromFieldInfo.Interface().(time.Time)
134-
toFieldInfo.Set(reflect.ValueOf(TimeToUnix(fromTime)))
135-
isSet = true
136-
} else if dm.DefaultTimeWrapper.IsType(toFieldInfo) && fromFieldInfo.Kind() == reflect.Int64 {
137-
fromTime := fromFieldInfo.Interface().(int64)
138-
toFieldInfo.Set(reflect.ValueOf(UnixToTime(fromTime)))
139-
isSet = true
140-
}
141-
}
142-
if !isSet {
143-
toFieldInfo.Set(fromFieldInfo)
153+
toFieldInfo.Set(x)
154+
}
155+
} else {
156+
isSet := false
157+
if dm.enabledAutoTypeConvert {
158+
if dm.DefaultTimeWrapper.IsType(fromFieldInfo) && toFieldInfo.Kind() == reflect.Int64 {
159+
fromTime := fromFieldInfo.Interface().(time.Time)
160+
toFieldInfo.Set(reflect.ValueOf(TimeToUnix(fromTime)))
161+
isSet = true
162+
} else if dm.DefaultTimeWrapper.IsType(toFieldInfo) && fromFieldInfo.Kind() == reflect.Int64 {
163+
fromTime := fromFieldInfo.Interface().(int64)
164+
toFieldInfo.Set(reflect.ValueOf(UnixToTime(fromTime)))
165+
isSet = true
144166
}
145167
}
146-
168+
if !isSet {
169+
toFieldInfo.Set(fromFieldInfo)
170+
}
147171
}
172+
return nil
148173
}
149174

150175
func (dm *mapperObject) elemToMap(fromElem, toElem reflect.Value) {

version.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
## devfeel/mapper
22

3+
#### Version 0.7.13
4+
* Feature: Added the "composite-field" tag to continue expanding and searching for corresponding field mappings when encountering composite fields in a Struct. Currently, only one level of expansion is supported.
5+
* Tips: Thanks to @naeemaei for issue #39
6+
* For my birthday!
7+
* you can use like this:
8+
``` go
9+
// Base model
10+
type BaseModel struct {
11+
Id int `json:"id"`
12+
}
13+
14+
// Country model
15+
type Country struct {
16+
BaseModel `json:"composite-field"`
17+
Name string `json:"name"`
18+
}
19+
```
20+
* 2023-04-15 19:00 in ShangHai
21+
322
#### Version 0.7.12
423
* Refactor: Solve the problem of repeated function implementation, rewrite "mapperObject.Getfieldname" direct call "mapperObject.getFieldName".
524
* Refactor: Rewrite mapperObject.cleanRegisterValue, it will be reset registerMap & fieldNameMap.

0 commit comments

Comments
 (0)