improve gconv.Map/String

This commit is contained in:
John
2020-01-03 20:23:10 +08:00
parent 344f232c36
commit bc53f265af
7 changed files with 105 additions and 37 deletions

View File

@ -0,0 +1,25 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
type User struct {
Id int `json:"id"`
Name string `json:"name"`
Pass1 string `json:"password1" p:"password1"`
Pass2 string `json:"password2" p:"password2"`
}
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
var user *User
if err := r.Parse(&user); err != nil {
r.Response.WriteExit(err)
}
r.Response.WriteExit(user)
})
s.SetPort(8199)
s.Run()
}

View File

@ -0,0 +1,36 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
type RegisterReq struct {
Name string
Pass string `p:"password1"`
Pass2 string `p:"password2"`
}
type RegisterRes struct {
Code int `json:"code"`
Error string `json:"error"`
Data interface{} `json:"data"`
}
func main() {
s := g.Server()
s.BindHandler("/register", func(r *ghttp.Request) {
var req *RegisterReq
if err := r.Parse(&req); err != nil {
r.Response.WriteJsonExit(RegisterRes{
Code: 1,
Error: err.Error(),
})
}
r.Response.WriteJsonExit(RegisterRes{
Data: req,
})
})
s.SetPort(8199)
s.Run()
}

View File

@ -1,32 +1,27 @@
package main
import (
"github.com/gogf/gf/frame/g"
"fmt"
"github.com/gogf/gf/util/gconv"
)
func main() {
type Ids struct {
Id int `c:"id"`
Uid int `c:"uid"`
}
type Base struct {
Ids
Id int `c:"id"`
CreateTime string `c:"create_time"`
}
type User struct {
Base
Base `c:"base"`
Passport string `c:"passport"`
Password string `c:"password"`
Nickname string `c:"nickname"`
}
user := new(User)
user.Id = 1
user.Uid = 100
user.Nickname = "John"
user.Passport = "johng"
user.Password = "123456"
user.CreateTime = "2019"
g.Dump(gconv.Map(user))
g.Dump(gconv.MapDeep(user))
fmt.Println(gconv.Map(user))
fmt.Println(gconv.MapDeep(user))
}

View File

@ -252,17 +252,20 @@ func Test_DB_BatchInsert(t *testing.T) {
gtest.Assert(n, 1)
})
}
func Test_DB_BatchInsert_Struct(t *testing.T) {
// batch insert struct
gtest.Case(t, func() {
table := createTable()
defer dropTable(table)
type User struct {
Id int `gconv:"id"`
Passport string `gconv:"passport"`
Password string `gconv:"password"`
NickName string `gconv:"nickname"`
CreateTime *gtime.Time `gconv:"create_time"`
Id int `c:"id"`
Passport string `c:"passport"`
Password string `c:"password"`
NickName string `c:"nickname"`
CreateTime *gtime.Time `c:"create_time"`
}
user := &User{
Id: 1,
@ -276,7 +279,6 @@ func Test_DB_BatchInsert(t *testing.T) {
n, _ := result.RowsAffected()
gtest.Assert(n, 1)
})
}
func Test_DB_Save(t *testing.T) {

View File

@ -10,7 +10,6 @@ package gconv
import (
"encoding/json"
"fmt"
"github.com/gogf/gf/internal/empty"
"github.com/gogf/gf/os/gtime"
"reflect"
"strconv"
@ -213,7 +212,8 @@ func String(i interface{}) string {
}
return value.String()
default:
if empty.IsNil(value) {
// Empty checks.
if value == nil {
return ""
}
if f, ok := value.(apiString); ok {
@ -225,6 +225,24 @@ func String(i interface{}) string {
// then use that interface to perform the conversion
return f.Error()
} else {
// Reflect checks.
rv := reflect.ValueOf(value)
kind := rv.Kind()
switch kind {
case reflect.Chan,
reflect.Map,
reflect.Slice,
reflect.Func,
reflect.Ptr,
reflect.Interface,
reflect.UnsafePointer:
if rv.IsNil() {
return ""
}
}
if kind == reflect.Ptr {
return String(rv.Elem().Interface())
}
// Finally we use json.Marshal to convert.
if jsonContent, err := json.Marshal(value); err != nil {
return fmt.Sprint(value)

View File

@ -45,7 +45,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
if r, ok := value.(map[string]interface{}); ok {
return r
} else {
// Only assert the common combination of types, and finally it uses reflection.
// Assert the common combination of types, and finally it uses reflection.
m := make(map[string]interface{})
switch value.(type) {
case map[interface{}]interface{}:
@ -104,7 +104,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
for k, v := range value.(map[uint]string) {
m[String(k)] = v
}
// Not a common type, use reflection
// Not a common type, then use reflection.
default:
rv := reflect.ValueOf(value)
kind := rv.Kind()
@ -136,6 +136,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
}
var rtField reflect.StructField
var rvField reflect.Value
var rvKind reflect.Kind
for i := 0; i < rv.NumField(); i++ {
rtField = rt.Field(i)
rvField = rv.Field(i)
@ -173,28 +174,20 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
}
}
}
switch rvField.Kind() {
case reflect.Ptr:
if rvField.Elem().Kind() == reflect.Struct {
if recursive {
for k, v := range doMapConvert(rvField.Interface(), recursive, tags...) {
m[k] = v
}
} else {
m[name] = doMapConvert(rvField.Interface(), recursive, tags...)
}
} else {
m[name] = rvField.Interface()
if recursive {
rvKind = rvField.Kind()
if rvKind == reflect.Ptr {
rvField = rvField.Elem()
rvKind = rvField.Kind()
}
case reflect.Struct:
if recursive {
if rvKind == reflect.Struct {
for k, v := range doMapConvert(rvField.Interface(), recursive, tags...) {
m[k] = v
}
} else {
m[name] = doMapConvert(rvField.Interface(), recursive, tags...)
m[name] = rvField.Interface()
}
default:
} else {
m[name] = rvField.Interface()
}
}

View File

@ -940,7 +940,6 @@ func Test_Map_StructInherit_All(t *testing.T) {
func Test_Struct_Basic1_All(t *testing.T) {
gtest.Case(t, func() {
type Score struct {
Name int
Result string