improve package gconv/cli

This commit is contained in:
John Guo 2022-02-22 20:19:41 +08:00
parent aa6705f493
commit d9c1e1f576
3 changed files with 96 additions and 43 deletions

View File

@ -512,11 +512,12 @@ func generateDaoInternal(
}
func replaceDefaultVar(in cGenDaoInternalInput, origin string) string {
if !in.WithTime {
return origin
var tplDatetimeStr string
if in.WithTime {
tplDatetimeStr = fmt.Sprintf(`Created at %s`, createdAt.String())
}
return gstr.ReplaceByMap(origin, g.MapStrStr{
tplVarDatetimeStr: createdAt.String(),
tplVarDatetimeStr: tplDatetimeStr,
})
}

View File

@ -453,51 +453,84 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
// Note that the slice element might be type of struct,
// so it uses Struct function doing the converting internally.
case reflect.Slice, reflect.Array:
a := reflect.Value{}
v := reflect.ValueOf(value)
if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
a = reflect.MakeSlice(structFieldValue.Type(), v.Len(), v.Len())
if v.Len() > 0 {
t := a.Index(0).Type()
for i := 0; i < v.Len(); i++ {
if t.Kind() == reflect.Ptr {
e := reflect.New(t.Elem()).Elem()
if err = doStruct(v.Index(i).Interface(), e, nil, ""); err != nil {
// Note there's reflect conversion mechanism here.
e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
}
a.Index(i).Set(e.Addr())
} else {
e := reflect.New(t).Elem()
if err = doStruct(v.Index(i).Interface(), e, nil, ""); err != nil {
// Note there's reflect conversion mechanism here.
e.Set(reflect.ValueOf(v.Index(i).Interface()).Convert(t))
}
a.Index(i).Set(e)
var (
reflectArray reflect.Value
reflectValue = reflect.ValueOf(value)
)
if reflectValue.Kind() == reflect.Slice || reflectValue.Kind() == reflect.Array {
reflectArray = reflect.MakeSlice(structFieldValue.Type(), reflectValue.Len(), reflectValue.Len())
if reflectValue.Len() > 0 {
var (
elemType = reflectArray.Index(0).Type()
elemTypeName string
converted bool
)
for i := 0; i < reflectValue.Len(); i++ {
converted = false
elemTypeName = elemType.Name()
if elemTypeName == "" {
elemTypeName = elemType.String()
}
var elem reflect.Value
if elemType.Kind() == reflect.Ptr {
elem = reflect.New(elemType.Elem()).Elem()
} else {
elem = reflect.New(elemType).Elem()
}
if elem.Kind() == reflect.Struct {
if err = doStruct(reflectValue.Index(i).Interface(), elem, nil, ""); err == nil {
converted = true
}
}
if !converted {
elem.Set(reflect.ValueOf(doConvert(doConvertInput{
FromValue: reflectValue.Index(i).Interface(),
ToTypeName: elemTypeName,
ReferValue: elem,
})))
}
if elemType.Kind() == reflect.Ptr {
// Before it sets the `elem` to array, do pointer converting if necessary.
elem = elem.Addr()
}
reflectArray.Index(i).Set(elem)
}
}
} else {
a = reflect.MakeSlice(structFieldValue.Type(), 1, 1)
t := a.Index(0).Type()
if t.Kind() == reflect.Ptr {
// Pointer element.
e := reflect.New(t.Elem()).Elem()
if err = doStruct(value, e, nil, ""); err != nil {
// Note there's reflect conversion mechanism here.
e.Set(reflect.ValueOf(value).Convert(t))
}
a.Index(0).Set(e.Addr())
} else {
// Just consider it as struct element. (Although it might be other types but not basic types, eg: map)
e := reflect.New(t).Elem()
if err = doStruct(value, e, nil, ""); err != nil {
return err
}
a.Index(0).Set(e)
reflectArray = reflect.MakeSlice(structFieldValue.Type(), 1, 1)
var (
elem reflect.Value
elemType = reflectArray.Index(0).Type()
elemTypeName = elemType.Name()
converted bool
)
if elemTypeName == "" {
elemTypeName = elemType.String()
}
if elemType.Kind() == reflect.Ptr {
elem = reflect.New(elemType.Elem()).Elem()
} else {
elem = reflect.New(elemType).Elem()
}
if elem.Kind() == reflect.Struct {
if err = doStruct(value, elem, nil, ""); err == nil {
converted = true
}
}
if !converted {
elem.Set(reflect.ValueOf(doConvert(doConvertInput{
FromValue: value,
ToTypeName: elemTypeName,
ReferValue: elem,
})))
}
if elemType.Kind() == reflect.Ptr {
// Before it sets the `elem` to array, do pointer converting if necessary.
elem = elem.Addr()
}
reflectArray.Index(0).Set(elem)
}
structFieldValue.Set(a)
structFieldValue.Set(reflectArray)
case reflect.Ptr:
item := reflect.New(structFieldValue.Type().Elem())

View File

@ -356,7 +356,7 @@ func Test_Struct_Attr_CustomType2(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
user := new(User)
err := gconv.Struct(g.Map{"id": g.Slice{1, 2}, "name": "john"}, user)
t.Assert(err, nil)
t.AssertNil(err)
t.Assert(user.Id, g.Slice{1, 2})
t.Assert(user.Name, "john")
})
@ -1301,3 +1301,22 @@ func Test_Struct_Issue1597(t *testing.T) {
t.Assert(s.B, `{"c":3}`)
})
}
func Test_Scan_WithDoubleSliceAttribute(t *testing.T) {
inputData := [][]string{
{"aa", "bb", "cc"},
{"11", "22", "33"},
}
data := struct {
Data [][]string
}{
Data: inputData,
}
gtest.C(t, func(t *gtest.T) {
jv := gjson.New(gjson.MustEncodeString(data))
err := jv.Scan(&data)
t.AssertNil(err)
t.Assert(data.Data, inputData)
})
}