Skip to content

Commit

Permalink
improved toExportedName and trySolveTargetName
Browse files Browse the repository at this point in the history
  • Loading branch information
hedzr committed Nov 1, 2024
1 parent 78184bc commit 4612746
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 55 deletions.
78 changes: 40 additions & 38 deletions ctrl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1353,30 +1353,6 @@ func TestMapToString(t *testing.T) { //nolint:revive
// tm2 := time.Date(2003, 9, 1, 23, 59, 59, 3579, timeZone)
// tm3 := time.Date(2015, 1, 29, 19, 31, 37, 77, timeZone2)

expect2 := evendeep.User{
Name: "Bob",
Birthday: &tm,
Age: 24,
EmployeID: 7,
Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
Image: []byte{95, 27, 43, 66, 0, 21, 210},
Attr: &evendeep.Attr{Attrs: []string{helloString, worldString}},
Valid: true,
}

expect3 := evendeep.Employee2{
Base: evendeep.Base{
Name: "Bob",
Birthday: &tm,
Age: 24,
EmployeID: 7,
},
Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
Image: []byte{95, 27, 43, 66, 0, 21, 210},
Attr: &evendeep.Attr{Attrs: []string{helloString, worldString}},
Valid: true,
}

var s2 evendeep.User
var s3 evendeep.Employee2
var str1 string
Expand Down Expand Up @@ -1411,20 +1387,31 @@ func TestMapToString(t *testing.T) { //nolint:revive
"Valid": true
}`

cases := []evendeep.TestCase{
evendeep.NewTestCase(
"map -> string [json]",
map1, &str1, &expect1,
[]evendeep.Opt{
evendeep.WithStringMarshaller(func(v interface{}) ([]byte, error) { //nolint:revive
return json.MarshalIndent(v, "", " ")
}),
evendeep.WithMergeStrategyOpt,
evendeep.WithAutoExpandStructOpt,
},
nil,
),
expect2 := evendeep.User{
Name: "Bob",
Birthday: &tm,
Age: 24,
EmployeID: 7,
Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
Image: []byte{95, 27, 43, 66, 0, 21, 210},
Attr: &evendeep.Attr{Attrs: []string{helloString, worldString}},
Valid: true,
}

expect3 := evendeep.Employee2{
Base: evendeep.Base{
Name: "Bob",
Birthday: &tm,
Age: 24,
EmployeID: 7,
},
Avatar: "https://tse4-mm.cn.bing.net/th/id/OIP-C.SAy__OKoxrIqrXWAb7Tj1wHaEC?pid=ImgDet&rs=1",
Image: []byte{95, 27, 43, 66, 0, 21, 210},
Attr: &evendeep.Attr{Attrs: []string{helloString, worldString}},
Valid: true,
}

cases := []evendeep.TestCase{
evendeep.NewTestCase(
"map -> struct User",
map1, &s2, &expect2,
Expand All @@ -1437,12 +1424,27 @@ func TestMapToString(t *testing.T) { //nolint:revive
[]evendeep.Opt{evendeep.WithMergeStrategyOpt, evendeep.WithAutoExpandStructOpt},
nil,
),
evendeep.NewTestCase(
"map -> string [json]",
map1, &str1, &expect1,
[]evendeep.Opt{
evendeep.WithStringMarshaller(func(v interface{}) ([]byte, error) { //nolint:revive
return json.MarshalIndent(v, "", " ")
}),
evendeep.WithMergeStrategyOpt,
evendeep.WithAutoExpandStructOpt,
},
nil,
),
}

for ix, tc := range cases {
if !t.Run(fmt.Sprintf("%3d. %s", ix, tc.Description), evendeep.DefaultDeepCopyTestRunner(ix, tc)) {
desc := fmt.Sprintf("%3d. %s", ix, tc.Description)
tr := evendeep.DefaultDeepCopyTestRunner(ix, tc)
if !t.Run(desc, tr) {
break
}
t.Logf("%5d. passed ----------------", ix)
}
}

Expand Down
88 changes: 71 additions & 17 deletions cvts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2037,12 +2037,35 @@ func (c *fromMapConverter) toStructDirectly(ctx *ValueConverterContext, source,
return
}

const tryForExportedFieldName = true
const trySmartFieldName = true

func toExportedName(s string) string {
if s != "" {
a := wordSplitter(s)
for i, word := range a {
a[i] = makeCapitalize1st(word)

if trySmartFieldName {
// https://go.dev/wiki/CodeReviewComments#initialisms
var smartTrans = map[string]string{
"tls": "TLS",
"json": "JSON", "toml": "TOML", "yaml": "YAML", "xml": "XML",
"id": "ID",
"url": "URL", "http": "HTTP", "uri": "URI",
"nato": "NATO",
}
for i, word := range a {
if t, ok := smartTrans[string(word)]; ok {
a[i] = []rune(t)
} else {
a[i] = makeCapitalize1st(word)
}
}
} else {
for i, word := range a {
a[i] = makeCapitalize1st(word)
}
}

var r []rune
for _, word := range a {
r = append(r, word...)
Expand Down Expand Up @@ -2103,6 +2126,34 @@ func (c *fromMapConverter) toStruct(ctx *ValueConverterContext, source reflect.V
return
}

trySolveTargetName := func(keyStr, targetName string, structType reflect.Type) (tsf reflect.StructField, fieldName string, solved bool) {
// use the key.(string) as the target struct field name
tsf, solved = targetType.FieldByName(targetName)
if !solved {
if tryForExportedFieldName {
if fieldName = toExportedName(keyStr); fieldName != keyStr {
tsf, solved = targetType.FieldByName(fieldName)
}
}
if !solved {
for i := 0; i < structType.NumField(); i++ {
fld := structType.Field(i)
f, r := flags.Parse(fld.Tag, flags.CopyTagName)
if r.Valid() && r.ToName() == keyStr {
tsf, fieldName, solved = fld, fld.Name, true
_ = f
return
}
}
} else {
// ks = fieldName
return
}
}
fieldName = keyStr
return
}

ec := errors.New("map -> struct errors")
defer ec.Defer(&err)

Expand Down Expand Up @@ -2135,22 +2186,25 @@ func (c *fromMapConverter) toStruct(ctx *ValueConverterContext, source reflect.V
}
}

const tryForExportedFieldName = true

// use the key.(string) as the target struct field name
tsf, ok := targetType.FieldByName(ks)
tsf, kstmp, ok := trySolveTargetName(ks, ks, targetType)
if !ok {
var kS string
if tryForExportedFieldName {
if kS = toExportedName(ks); kS != ks {
tsf, ok = targetType.FieldByName(kS)
}
}
if !ok {
continue
}
ks = kS
continue
}
ks = kstmp
// // use the key.(string) as the target struct field name
// tsf, ok := targetType.FieldByName(ks)
// if !ok {
// var kS string
// if tryForExportedFieldName {
// if kS = toExportedName(ks); kS != ks {
// tsf, ok = targetType.FieldByName(kS)
// }
// }
// if !ok {
// continue
// }
// ks = kS
// }

fld := target.FieldByName(ks)
// dbglog.Log(" fld %q: ", ks)
Expand All @@ -2161,7 +2215,7 @@ func (c *fromMapConverter) toStruct(ctx *ValueConverterContext, source reflect.V
fld = fld.Elem()
} else if tsfk == reflect.Ptr {
dbglog.Log(" fld.%q: %v (%v)", ks, ref.Valfmt(&fld), ref.Typfmtv(&fld))
if fld.IsNil() {
if ref.IsNil(fld) {
n := reflect.New(fld.Type().Elem())
target.FieldByName(ks).Set(n)
fld = target.FieldByName(ks)
Expand Down

0 comments on commit 4612746

Please sign in to comment.