github.com/gogf/gf@v1.16.9/util/gconv/gconv_z_unit_struct_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"github.com/gogf/gf/container/gvar"
    11  	"github.com/gogf/gf/frame/g"
    12  	"github.com/gogf/gf/internal/json"
    13  	"github.com/gogf/gf/os/gtime"
    14  	"github.com/gogf/gf/test/gtest"
    15  	"github.com/gogf/gf/util/gconv"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  func Test_Struct_Basic1(t *testing.T) {
    21  	gtest.C(t, func(t *gtest.T) {
    22  		type User struct {
    23  			Uid      int
    24  			Name     string
    25  			Site_Url string
    26  			NickName string
    27  			Pass1    string `gconv:"password1"`
    28  			Pass2    string `gconv:"password2"`
    29  		}
    30  		user := new(User)
    31  		params1 := g.Map{
    32  			"uid":       1,
    33  			"Name":      "john",
    34  			"siteurl":   "https://goframe.org",
    35  			"nick_name": "johng",
    36  			"PASS1":     "123",
    37  			"PASS2":     "456",
    38  		}
    39  		if err := gconv.Struct(params1, user); err != nil {
    40  			t.Error(err)
    41  		}
    42  		t.Assert(user, &User{
    43  			Uid:      1,
    44  			Name:     "john",
    45  			Site_Url: "https://goframe.org",
    46  			NickName: "johng",
    47  			Pass1:    "123",
    48  			Pass2:    "456",
    49  		})
    50  
    51  		user = new(User)
    52  		params2 := g.Map{
    53  			"uid":       2,
    54  			"name":      "smith",
    55  			"site-url":  "https://goframe.org",
    56  			"nick name": "johng",
    57  			"password1": "111",
    58  			"password2": "222",
    59  		}
    60  		if err := gconv.Struct(params2, user); err != nil {
    61  			t.Error(err)
    62  		}
    63  		t.Assert(user, &User{
    64  			Uid:      2,
    65  			Name:     "smith",
    66  			Site_Url: "https://goframe.org",
    67  			NickName: "johng",
    68  			Pass1:    "111",
    69  			Pass2:    "222",
    70  		})
    71  	})
    72  }
    73  
    74  func Test_Struct_Basic2(t *testing.T) {
    75  	gtest.C(t, func(t *gtest.T) {
    76  		type User struct {
    77  			Uid     int
    78  			Name    string
    79  			SiteUrl string
    80  			Pass1   string
    81  			Pass2   string
    82  		}
    83  		user := new(User)
    84  		params := g.Map{
    85  			"uid":      1,
    86  			"Name":     "john",
    87  			"site_url": "https://goframe.org",
    88  			"PASS1":    "123",
    89  			"PASS2":    "456",
    90  		}
    91  		if err := gconv.Struct(params, user); err != nil {
    92  			t.Error(err)
    93  		}
    94  		t.Assert(user, &User{
    95  			Uid:     1,
    96  			Name:    "john",
    97  			SiteUrl: "https://goframe.org",
    98  			Pass1:   "123",
    99  			Pass2:   "456",
   100  		})
   101  	})
   102  }
   103  
   104  func Test_Struct_Attr_Pointer(t *testing.T) {
   105  	gtest.C(t, func(t *gtest.T) {
   106  		type User struct {
   107  			Uid  *int
   108  			Name *string
   109  		}
   110  		user := new(User)
   111  		params := g.Map{
   112  			"uid":  "1",
   113  			"Name": "john",
   114  		}
   115  		if err := gconv.Struct(params, user); err != nil {
   116  			t.Error(err)
   117  		}
   118  		t.Assert(user.Uid, 1)
   119  		t.Assert(*user.Name, "john")
   120  	})
   121  }
   122  
   123  func Test_Struct_Attr_Slice1(t *testing.T) {
   124  	gtest.C(t, func(t *gtest.T) {
   125  		type User struct {
   126  			Scores []int
   127  		}
   128  		scores := []interface{}{99, 100, 60, 140}
   129  		user := new(User)
   130  		if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil {
   131  			t.Error(err)
   132  		} else {
   133  			t.Assert(user, &User{
   134  				Scores: []int{99, 100, 60, 140},
   135  			})
   136  		}
   137  	})
   138  }
   139  
   140  // It does not support this kind of converting yet.
   141  //func Test_Struct_Attr_Slice2(t *testing.T) {
   142  //	gtest.C(t, func(t *gtest.T) {
   143  //		type User struct {
   144  //			Scores [][]int
   145  //		}
   146  //		scores := []interface{}{[]interface{}{99, 100, 60, 140}}
   147  //		user := new(User)
   148  //		if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil {
   149  //			t.Error(err)
   150  //		} else {
   151  //			t.Assert(user, &User{
   152  //				Scores: [][]int{{99, 100, 60, 140}},
   153  //			})
   154  //		}
   155  //	})
   156  //}
   157  
   158  func Test_Struct_Attr_Struct(t *testing.T) {
   159  	gtest.C(t, func(t *gtest.T) {
   160  		type Score struct {
   161  			Name   string
   162  			Result int
   163  		}
   164  		type User struct {
   165  			Scores Score
   166  		}
   167  
   168  		user := new(User)
   169  		scores := map[string]interface{}{
   170  			"Scores": map[string]interface{}{
   171  				"Name":   "john",
   172  				"Result": 100,
   173  			},
   174  		}
   175  
   176  		// 嵌套struct转换
   177  		if err := gconv.Struct(scores, user); err != nil {
   178  			t.Error(err)
   179  		} else {
   180  			t.Assert(user, &User{
   181  				Scores: Score{
   182  					Name:   "john",
   183  					Result: 100,
   184  				},
   185  			})
   186  		}
   187  	})
   188  }
   189  
   190  func Test_Struct_Attr_Struct_Ptr(t *testing.T) {
   191  	gtest.C(t, func(t *gtest.T) {
   192  		type Score struct {
   193  			Name   string
   194  			Result int
   195  		}
   196  		type User struct {
   197  			Scores *Score
   198  		}
   199  
   200  		user := new(User)
   201  		scores := map[string]interface{}{
   202  			"Scores": map[string]interface{}{
   203  				"Name":   "john",
   204  				"Result": 100,
   205  			},
   206  		}
   207  
   208  		// 嵌套struct转换
   209  		if err := gconv.Struct(scores, user); err != nil {
   210  			t.Error(err)
   211  		} else {
   212  			t.Assert(user.Scores, &Score{
   213  				Name:   "john",
   214  				Result: 100,
   215  			})
   216  		}
   217  	})
   218  }
   219  
   220  func Test_Struct_Attr_Struct_Slice1(t *testing.T) {
   221  	gtest.C(t, func(t *gtest.T) {
   222  		type Score struct {
   223  			Name   string
   224  			Result int
   225  		}
   226  		type User struct {
   227  			Scores []Score
   228  		}
   229  
   230  		user := new(User)
   231  		scores := map[string]interface{}{
   232  			"Scores": map[string]interface{}{
   233  				"Name":   "john",
   234  				"Result": 100,
   235  			},
   236  		}
   237  
   238  		if err := gconv.Struct(scores, user); err != nil {
   239  			t.Error(err)
   240  		} else {
   241  			t.Assert(user.Scores, []Score{
   242  				{
   243  					Name:   "john",
   244  					Result: 100,
   245  				},
   246  			})
   247  		}
   248  	})
   249  }
   250  
   251  func Test_Struct_Attr_Struct_Slice2(t *testing.T) {
   252  	gtest.C(t, func(t *gtest.T) {
   253  		type Score struct {
   254  			Name   string
   255  			Result int
   256  		}
   257  		type User struct {
   258  			Scores []Score
   259  		}
   260  
   261  		user := new(User)
   262  		scores := map[string]interface{}{
   263  			"Scores": []interface{}{
   264  				map[string]interface{}{
   265  					"Name":   "john",
   266  					"Result": 100,
   267  				},
   268  				map[string]interface{}{
   269  					"Name":   "smith",
   270  					"Result": 60,
   271  				},
   272  			},
   273  		}
   274  
   275  		if err := gconv.Struct(scores, user); err != nil {
   276  			t.Error(err)
   277  		} else {
   278  			t.Assert(user.Scores, []Score{
   279  				{
   280  					Name:   "john",
   281  					Result: 100,
   282  				},
   283  				{
   284  					Name:   "smith",
   285  					Result: 60,
   286  				},
   287  			})
   288  		}
   289  	})
   290  }
   291  
   292  func Test_Struct_Attr_Struct_Slice_Ptr(t *testing.T) {
   293  	gtest.C(t, func(t *gtest.T) {
   294  		type Score struct {
   295  			Name   string
   296  			Result int
   297  		}
   298  		type User struct {
   299  			Scores []*Score
   300  		}
   301  
   302  		user := new(User)
   303  		scores := map[string]interface{}{
   304  			"Scores": []interface{}{
   305  				map[string]interface{}{
   306  					"Name":   "john",
   307  					"Result": 100,
   308  				},
   309  				map[string]interface{}{
   310  					"Name":   "smith",
   311  					"Result": 60,
   312  				},
   313  			},
   314  		}
   315  
   316  		// 嵌套struct转换,属性为slice类型,数值为slice map类型
   317  		if err := gconv.Struct(scores, user); err != nil {
   318  			t.Error(err)
   319  		} else {
   320  			t.Assert(len(user.Scores), 2)
   321  			t.Assert(user.Scores[0], &Score{
   322  				Name:   "john",
   323  				Result: 100,
   324  			})
   325  			t.Assert(user.Scores[1], &Score{
   326  				Name:   "smith",
   327  				Result: 60,
   328  			})
   329  		}
   330  	})
   331  }
   332  
   333  func Test_Struct_Attr_CustomType1(t *testing.T) {
   334  	type MyInt int
   335  	type User struct {
   336  		Id   MyInt
   337  		Name string
   338  	}
   339  	gtest.C(t, func(t *gtest.T) {
   340  		user := new(User)
   341  		err := gconv.Struct(g.Map{"id": 1, "name": "john"}, user)
   342  		t.Assert(err, nil)
   343  		t.Assert(user.Id, 1)
   344  		t.Assert(user.Name, "john")
   345  	})
   346  }
   347  
   348  func Test_Struct_Attr_CustomType2(t *testing.T) {
   349  	type MyInt int
   350  	type User struct {
   351  		Id   []MyInt
   352  		Name string
   353  	}
   354  	gtest.C(t, func(t *gtest.T) {
   355  		user := new(User)
   356  		err := gconv.Struct(g.Map{"id": g.Slice{1, 2}, "name": "john"}, user)
   357  		t.Assert(err, nil)
   358  		t.Assert(user.Id, g.Slice{1, 2})
   359  		t.Assert(user.Name, "john")
   360  	})
   361  }
   362  
   363  // From: k8s.io/apimachinery@v0.22.0/pkg/apis/meta/v1/duration.go
   364  type MyDuration struct {
   365  	time.Duration
   366  }
   367  
   368  // UnmarshalJSON implements the json.Unmarshaller interface.
   369  func (d *MyDuration) UnmarshalJSON(b []byte) error {
   370  	var str string
   371  	err := json.Unmarshal(b, &str)
   372  	if err != nil {
   373  		return err
   374  	}
   375  
   376  	pd, err := time.ParseDuration(str)
   377  	if err != nil {
   378  		return err
   379  	}
   380  	d.Duration = pd
   381  	return nil
   382  }
   383  
   384  func Test_Struct_Attr_CustomType3(t *testing.T) {
   385  	type Config struct {
   386  		D MyDuration
   387  	}
   388  	gtest.C(t, func(t *gtest.T) {
   389  		config := new(Config)
   390  		err := gconv.Struct(g.Map{"d": "15s"}, config)
   391  		t.AssertNil(err)
   392  		t.Assert(config.D, "15s")
   393  	})
   394  	gtest.C(t, func(t *gtest.T) {
   395  		config := new(Config)
   396  		err := gconv.Struct(g.Map{"d": `"15s"`}, config)
   397  		t.AssertNil(err)
   398  		t.Assert(config.D, "15s")
   399  	})
   400  }
   401  
   402  func Test_Struct_PrivateAttribute(t *testing.T) {
   403  	type User struct {
   404  		Id   int
   405  		name string
   406  	}
   407  	gtest.C(t, func(t *gtest.T) {
   408  		user := new(User)
   409  		err := gconv.Struct(g.Map{"id": 1, "name": "john"}, user)
   410  		t.Assert(err, nil)
   411  		t.Assert(user.Id, 1)
   412  		t.Assert(user.name, "")
   413  	})
   414  }
   415  
   416  func Test_StructEmbedded1(t *testing.T) {
   417  	type Base struct {
   418  		Age int
   419  	}
   420  	type User struct {
   421  		Id   int
   422  		Name string
   423  		Base
   424  	}
   425  	gtest.C(t, func(t *gtest.T) {
   426  		user := new(User)
   427  		params := g.Map{
   428  			"id":   1,
   429  			"name": "john",
   430  			"age":  18,
   431  		}
   432  		err := gconv.Struct(params, user)
   433  		t.Assert(err, nil)
   434  		t.Assert(user.Id, params["id"])
   435  		t.Assert(user.Name, params["name"])
   436  		t.Assert(user.Age, 18)
   437  	})
   438  }
   439  
   440  func Test_StructEmbedded2(t *testing.T) {
   441  	type Ids struct {
   442  		Id  int
   443  		Uid int
   444  	}
   445  	type Base struct {
   446  		Ids
   447  		Time string
   448  	}
   449  	type User struct {
   450  		Base
   451  		Name string
   452  	}
   453  	params := g.Map{
   454  		"id":   1,
   455  		"uid":  10,
   456  		"name": "john",
   457  	}
   458  	gtest.C(t, func(t *gtest.T) {
   459  		user := new(User)
   460  		err := gconv.Struct(params, user)
   461  		t.Assert(err, nil)
   462  		t.Assert(user.Id, 1)
   463  		t.Assert(user.Uid, 10)
   464  		t.Assert(user.Name, "john")
   465  	})
   466  }
   467  
   468  func Test_StructEmbedded3(t *testing.T) {
   469  	gtest.C(t, func(t *gtest.T) {
   470  		type Ids struct {
   471  			Id  int `json:"id"`
   472  			Uid int `json:"uid"`
   473  		}
   474  		type Base struct {
   475  			Ids
   476  			CreateTime string `json:"create_time"`
   477  		}
   478  		type User struct {
   479  			Base
   480  			Passport string `json:"passport"`
   481  			Password string `json:"password"`
   482  			Nickname string `json:"nickname"`
   483  		}
   484  		data := g.Map{
   485  			"id":          100,
   486  			"uid":         101,
   487  			"passport":    "t1",
   488  			"password":    "123456",
   489  			"nickname":    "T1",
   490  			"create_time": "2019",
   491  		}
   492  		user := new(User)
   493  		err := gconv.Struct(data, user)
   494  		t.Assert(err, nil)
   495  		t.Assert(user.Id, 100)
   496  		t.Assert(user.Uid, 101)
   497  		t.Assert(user.Nickname, "T1")
   498  		t.Assert(user.CreateTime, "2019")
   499  	})
   500  }
   501  
   502  // https://github.com/gogf/gf/issues/775
   503  func Test_StructEmbedded4(t *testing.T) {
   504  	gtest.C(t, func(t *gtest.T) {
   505  		type Sub2 struct {
   506  			SubName string
   507  		}
   508  		type sub1 struct {
   509  			Sub2
   510  			Name string
   511  		}
   512  		type Test struct {
   513  			Sub sub1 `json:"sub"`
   514  		}
   515  
   516  		data := `{
   517      "sub": {
   518  		"map":{"k":"v"},
   519          "Name": "name",
   520          "SubName": "subname"
   521      }}`
   522  
   523  		expect := Test{
   524  			Sub: sub1{
   525  				Name: "name",
   526  				Sub2: Sub2{
   527  					SubName: "subname",
   528  				},
   529  			},
   530  		}
   531  		tx := new(Test)
   532  		if err := gconv.Struct(data, &tx); err != nil {
   533  			panic(err)
   534  		}
   535  		t.Assert(tx, expect)
   536  	})
   537  }
   538  
   539  func Test_StructEmbedded5(t *testing.T) {
   540  	gtest.C(t, func(t *gtest.T) {
   541  		type Base struct {
   542  			Pass1 string `params:"password1"`
   543  			Pass2 string `params:"password2"`
   544  		}
   545  		type UserWithBase1 struct {
   546  			Id   int
   547  			Name string
   548  			Base
   549  		}
   550  		type UserWithBase2 struct {
   551  			Id   int
   552  			Name string
   553  			Pass Base
   554  		}
   555  
   556  		data := g.Map{
   557  			"id":        1,
   558  			"name":      "john",
   559  			"password1": "123",
   560  			"password2": "456",
   561  		}
   562  		var err error
   563  		user1 := new(UserWithBase1)
   564  		user2 := new(UserWithBase2)
   565  		err = gconv.Struct(data, user1)
   566  		t.Assert(err, nil)
   567  		t.Assert(user1, &UserWithBase1{1, "john", Base{"123", "456"}})
   568  
   569  		err = gconv.Struct(data, user2)
   570  		t.Assert(err, nil)
   571  		t.Assert(user2, &UserWithBase2{1, "john", Base{"", ""}})
   572  
   573  		var user3 *UserWithBase1
   574  		err = gconv.Struct(user1, &user3)
   575  		t.Assert(err, nil)
   576  		t.Assert(user3, user1)
   577  	})
   578  }
   579  
   580  func Test_Struct_Time(t *testing.T) {
   581  	gtest.C(t, func(t *gtest.T) {
   582  		type User struct {
   583  			CreateTime time.Time
   584  		}
   585  		now := time.Now()
   586  		user := new(User)
   587  		gconv.Struct(g.Map{
   588  			"create_time": now,
   589  		}, user)
   590  		t.Assert(user.CreateTime.UTC().String(), now.UTC().String())
   591  	})
   592  
   593  	gtest.C(t, func(t *gtest.T) {
   594  		type User struct {
   595  			CreateTime *time.Time
   596  		}
   597  		now := time.Now()
   598  		user := new(User)
   599  		gconv.Struct(g.Map{
   600  			"create_time": &now,
   601  		}, user)
   602  		t.Assert(user.CreateTime.UTC().String(), now.UTC().String())
   603  	})
   604  
   605  	gtest.C(t, func(t *gtest.T) {
   606  		type User struct {
   607  			CreateTime *gtime.Time
   608  		}
   609  		now := time.Now()
   610  		user := new(User)
   611  		gconv.Struct(g.Map{
   612  			"create_time": &now,
   613  		}, user)
   614  		t.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   615  	})
   616  
   617  	gtest.C(t, func(t *gtest.T) {
   618  		type User struct {
   619  			CreateTime gtime.Time
   620  		}
   621  		now := time.Now()
   622  		user := new(User)
   623  		gconv.Struct(g.Map{
   624  			"create_time": &now,
   625  		}, user)
   626  		t.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   627  	})
   628  
   629  	gtest.C(t, func(t *gtest.T) {
   630  		type User struct {
   631  			CreateTime gtime.Time
   632  		}
   633  		now := time.Now()
   634  		user := new(User)
   635  		gconv.Struct(g.Map{
   636  			"create_time": now,
   637  		}, user)
   638  		t.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   639  	})
   640  }
   641  
   642  func Test_Struct_GTime(t *testing.T) {
   643  	// https://github.com/gogf/gf/issues/1387
   644  	gtest.C(t, func(t *gtest.T) {
   645  		type User struct {
   646  			Name       string
   647  			CreateTime *gtime.Time
   648  		}
   649  		var user *User
   650  		err := gconv.Struct(`{"Name":"John","CreateTime":""}`, &user)
   651  		t.AssertNil(err)
   652  		t.AssertNE(user, nil)
   653  		t.Assert(user.Name, `John`)
   654  		t.Assert(user.CreateTime, nil)
   655  	})
   656  }
   657  
   658  // Auto create struct when given pointer.
   659  func Test_Struct_Create(t *testing.T) {
   660  	gtest.C(t, func(t *gtest.T) {
   661  		type User struct {
   662  			Uid  int
   663  			Name string
   664  		}
   665  		user := (*User)(nil)
   666  		params := g.Map{
   667  			"uid":  1,
   668  			"Name": "john",
   669  		}
   670  		err := gconv.Struct(params, &user)
   671  		t.Assert(err, nil)
   672  		t.Assert(user.Uid, 1)
   673  		t.Assert(user.Name, "john")
   674  	})
   675  
   676  	gtest.C(t, func(t *gtest.T) {
   677  		type User struct {
   678  			Uid  int
   679  			Name string
   680  		}
   681  		user := (*User)(nil)
   682  		params := g.Map{
   683  			"uid":  1,
   684  			"Name": "john",
   685  		}
   686  		err := gconv.Struct(params, user)
   687  		t.AssertNE(err, nil)
   688  		t.Assert(user, nil)
   689  	})
   690  }
   691  
   692  func Test_Struct_Interface(t *testing.T) {
   693  	gtest.C(t, func(t *gtest.T) {
   694  		type User struct {
   695  			Uid  interface{}
   696  			Name interface{}
   697  		}
   698  		user := (*User)(nil)
   699  		params := g.Map{
   700  			"uid":  1,
   701  			"Name": nil,
   702  		}
   703  		err := gconv.Struct(params, &user)
   704  		t.Assert(err, nil)
   705  		t.Assert(user.Uid, 1)
   706  		t.Assert(user.Name, nil)
   707  	})
   708  }
   709  
   710  func Test_Struct_NilAttribute(t *testing.T) {
   711  	gtest.C(t, func(t *gtest.T) {
   712  		type Item struct {
   713  			Title string `json:"title"`
   714  			Key   string `json:"key"`
   715  		}
   716  
   717  		type M struct {
   718  			Id    string                 `json:"id"`
   719  			Me    map[string]interface{} `json:"me"`
   720  			Txt   string                 `json:"txt"`
   721  			Items []*Item                `json:"items"`
   722  		}
   723  		m := new(M)
   724  		err := gconv.Struct(g.Map{
   725  			"id": "88888",
   726  			"me": g.Map{
   727  				"name": "mikey",
   728  				"day":  "20009",
   729  			},
   730  			"txt":   "hello",
   731  			"items": nil,
   732  		}, m)
   733  		t.Assert(err, nil)
   734  		t.AssertNE(m.Me, nil)
   735  		t.Assert(m.Me["day"], "20009")
   736  		t.Assert(m.Items, nil)
   737  	})
   738  }
   739  
   740  func Test_Struct_Complex(t *testing.T) {
   741  	gtest.C(t, func(t *gtest.T) {
   742  		type ApplyReportDetail struct {
   743  			ApplyScore        string `json:"apply_score"`
   744  			ApplyCredibility  string `json:"apply_credibility"`
   745  			QueryOrgCount     string `json:"apply_query_org_count"`
   746  			QueryFinanceCount string `json:"apply_query_finance_count"`
   747  			QueryCashCount    string `json:"apply_query_cash_count"`
   748  			QuerySumCount     string `json:"apply_query_sum_count"`
   749  			LatestQueryTime   string `json:"apply_latest_query_time"`
   750  			LatestOneMonth    string `json:"apply_latest_one_month"`
   751  			LatestThreeMonth  string `json:"apply_latest_three_month"`
   752  			LatestSixMonth    string `json:"apply_latest_six_month"`
   753  		}
   754  		type BehaviorReportDetail struct {
   755  			LoansScore         string `json:"behavior_report_detailloans_score"`
   756  			LoansCredibility   string `json:"behavior_report_detailloans_credibility"`
   757  			LoansCount         string `json:"behavior_report_detailloans_count"`
   758  			LoansSettleCount   string `json:"behavior_report_detailloans_settle_count"`
   759  			LoansOverdueCount  string `json:"behavior_report_detailloans_overdue_count"`
   760  			LoansOrgCount      string `json:"behavior_report_detailloans_org_count"`
   761  			ConsfinOrgCount    string `json:"behavior_report_detailconsfin_org_count"`
   762  			LoansCashCount     string `json:"behavior_report_detailloans_cash_count"`
   763  			LatestOneMonth     string `json:"behavior_report_detaillatest_one_month"`
   764  			LatestThreeMonth   string `json:"behavior_report_detaillatest_three_month"`
   765  			LatestSixMonth     string `json:"behavior_report_detaillatest_six_month"`
   766  			HistorySucFee      string `json:"behavior_report_detailhistory_suc_fee"`
   767  			HistoryFailFee     string `json:"behavior_report_detailhistory_fail_fee"`
   768  			LatestOneMonthSuc  string `json:"behavior_report_detaillatest_one_month_suc"`
   769  			LatestOneMonthFail string `json:"behavior_report_detaillatest_one_month_fail"`
   770  			LoansLongTime      string `json:"behavior_report_detailloans_long_time"`
   771  			LoansLatestTime    string `json:"behavior_report_detailloans_latest_time"`
   772  		}
   773  		type CurrentReportDetail struct {
   774  			LoansCreditLimit    string `json:"current_report_detailloans_credit_limit"`
   775  			LoansCredibility    string `json:"current_report_detailloans_credibility"`
   776  			LoansOrgCount       string `json:"current_report_detailloans_org_count"`
   777  			LoansProductCount   string `json:"current_report_detailloans_product_count"`
   778  			LoansMaxLimit       string `json:"current_report_detailloans_max_limit"`
   779  			LoansAvgLimit       string `json:"current_report_detailloans_avg_limit"`
   780  			ConsfinCreditLimit  string `json:"current_report_detailconsfin_credit_limit"`
   781  			ConsfinCredibility  string `json:"current_report_detailconsfin_credibility"`
   782  			ConsfinOrgCount     string `json:"current_report_detailconsfin_org_count"`
   783  			ConsfinProductCount string `json:"current_report_detailconsfin_product_count"`
   784  			ConsfinMaxLimit     string `json:"current_report_detailconsfin_max_limit"`
   785  			ConsfinAvgLimit     string `json:"current_report_detailconsfin_avg_limit"`
   786  		}
   787  		type ResultDetail struct {
   788  			ApplyReportDetail    ApplyReportDetail    `json:"apply_report_detail"`
   789  			BehaviorReportDetail BehaviorReportDetail `json:"behavior_report_detail"`
   790  			CurrentReportDetail  CurrentReportDetail  `json:"current_report_detail"`
   791  		}
   792  
   793  		type Data struct {
   794  			Code         string       `json:"code"`
   795  			Desc         string       `json:"desc"`
   796  			TransID      string       `json:"trans_id"`
   797  			TradeNo      string       `json:"trade_no"`
   798  			Fee          string       `json:"fee"`
   799  			IDNo         string       `json:"id_no"`
   800  			IDName       string       `json:"id_name"`
   801  			Versions     string       `json:"versions"`
   802  			ResultDetail ResultDetail `json:"result_detail"`
   803  		}
   804  
   805  		type XinYanModel struct {
   806  			Success   bool        `json:"success"`
   807  			Data      Data        `json:"data"`
   808  			ErrorCode interface{} `json:"errorCode"`
   809  			ErrorMsg  interface{} `json:"errorMsg"`
   810  		}
   811  
   812  		var data = `{
   813      "success": true,
   814      "data": {
   815          "code": "0",
   816          "desc": "查询成功",
   817          "trans_id": "14910304379231213",
   818          "trade_no": "201704011507240100057329",
   819          "fee": "Y",
   820          "id_no": "0783231bcc39f4957e99907e02ae401c",
   821          "id_name": "dd67a5943781369ddd7c594e231e9e70",
   822          "versions": "1.0.0",
   823          "result_detail":{
   824              "apply_report_detail": {
   825                  "apply_score": "189",
   826                  "apply_credibility": "84",
   827                  "query_org_count": "7",
   828                  "query_finance_count": "2",
   829                  "query_cash_count": "2",
   830                  "query_sum_count": "13",
   831                  "latest_query_time": "2017-09-03",
   832                  "latest_one_month": "1",
   833                  "latest_three_month": "5",
   834                  "latest_six_month": "12"
   835              },
   836              "behavior_report_detail": {
   837                  "loans_score": "199",
   838                  "loans_credibility": "90",
   839                  "loans_count": "300",
   840                  "loans_settle_count": "280",
   841                  "loans_overdue_count": "20",
   842                  "loans_org_count": "5",
   843                  "consfin_org_count": "3",
   844                  "loans_cash_count": "2",
   845                  "latest_one_month": "3",
   846                  "latest_three_month": "20",
   847                  "latest_six_month": "23",
   848                  "history_suc_fee": "30",
   849                  "history_fail_fee": "25",
   850                  "latest_one_month_suc": "5",
   851                  "latest_one_month_fail": "20",
   852                  "loans_long_time": "130",
   853                  "loans_latest_time": "2017-09-16"
   854              },
   855              "current_report_detail": {
   856                  "loans_credit_limit": "1400",
   857                  "loans_credibility": "80",
   858                  "loans_org_count": "7",
   859                  "loans_product_count": "8",
   860                  "loans_max_limit": "2000",
   861                  "loans_avg_limit": "1000",
   862                  "consfin_credit_limit": "1500",
   863                  "consfin_credibility": "90",
   864                  "consfin_org_count": "8",
   865                  "consfin_product_count": "5",
   866                  "consfin_max_limit": "5000",
   867                  "consfin_avg_limit": "3000"
   868              }
   869          }
   870      },
   871      "errorCode": null,
   872      "errorMsg": null
   873  }`
   874  		m := make(g.Map)
   875  		err := json.UnmarshalUseNumber([]byte(data), &m)
   876  		t.Assert(err, nil)
   877  
   878  		model := new(XinYanModel)
   879  		err = gconv.Struct(m, model)
   880  		t.Assert(err, nil)
   881  		t.Assert(model.ErrorCode, nil)
   882  		t.Assert(model.ErrorMsg, nil)
   883  		t.Assert(model.Success, true)
   884  		t.Assert(model.Data.IDName, "dd67a5943781369ddd7c594e231e9e70")
   885  		t.Assert(model.Data.TradeNo, "201704011507240100057329")
   886  		t.Assert(model.Data.ResultDetail.ApplyReportDetail.ApplyScore, "189")
   887  		t.Assert(model.Data.ResultDetail.BehaviorReportDetail.LoansSettleCount, "280")
   888  		t.Assert(model.Data.ResultDetail.CurrentReportDetail.LoansProductCount, "8")
   889  	})
   890  }
   891  
   892  func Test_Struct_CatchPanic(t *testing.T) {
   893  	gtest.C(t, func(t *gtest.T) {
   894  		type Score struct {
   895  			Name   string
   896  			Result int
   897  		}
   898  		type User struct {
   899  			Score Score
   900  		}
   901  
   902  		user := new(User)
   903  		scores := map[string]interface{}{
   904  			"Score": 1,
   905  		}
   906  		err := gconv.Struct(scores, user)
   907  		t.AssertNE(err, nil)
   908  	})
   909  }
   910  
   911  type T struct {
   912  	Name string
   913  }
   914  
   915  func (t *T) Test() string {
   916  	return t.Name
   917  }
   918  
   919  type TestInterface interface {
   920  	Test() string
   921  }
   922  
   923  type TestStruct struct {
   924  	TestInterface
   925  }
   926  
   927  func Test_Struct_Embedded(t *testing.T) {
   928  	// Implemented interface attribute.
   929  	gtest.C(t, func(t *gtest.T) {
   930  		v1 := TestStruct{
   931  			TestInterface: &T{"john"},
   932  		}
   933  		v2 := g.Map{}
   934  		err := gconv.Struct(v2, &v1)
   935  		t.Assert(err, nil)
   936  		t.Assert(v1.Test(), "john")
   937  	})
   938  	// Implemented interface attribute.
   939  	gtest.C(t, func(t *gtest.T) {
   940  		v1 := TestStruct{
   941  			TestInterface: &T{"john"},
   942  		}
   943  		v2 := g.Map{
   944  			"name": "test",
   945  		}
   946  		err := gconv.Struct(v2, &v1)
   947  		t.Assert(err, nil)
   948  		t.Assert(v1.Test(), "test")
   949  	})
   950  	// No implemented interface attribute.
   951  	gtest.C(t, func(t *gtest.T) {
   952  		v1 := TestStruct{}
   953  		v2 := g.Map{
   954  			"name": "test",
   955  		}
   956  		err := gconv.Struct(v2, &v1)
   957  		t.Assert(err, nil)
   958  		t.Assert(v1.TestInterface, nil)
   959  	})
   960  }
   961  
   962  func Test_Struct_Slice(t *testing.T) {
   963  	gtest.C(t, func(t *gtest.T) {
   964  		type User struct {
   965  			Scores []int
   966  		}
   967  		user := new(User)
   968  		array := g.Slice{1, 2, 3}
   969  		err := gconv.Struct(g.Map{"scores": array}, user)
   970  		t.Assert(err, nil)
   971  		t.Assert(user.Scores, array)
   972  	})
   973  	gtest.C(t, func(t *gtest.T) {
   974  		type User struct {
   975  			Scores []int32
   976  		}
   977  		user := new(User)
   978  		array := g.Slice{1, 2, 3}
   979  		err := gconv.Struct(g.Map{"scores": array}, user)
   980  		t.Assert(err, nil)
   981  		t.Assert(user.Scores, array)
   982  	})
   983  	gtest.C(t, func(t *gtest.T) {
   984  		type User struct {
   985  			Scores []int64
   986  		}
   987  		user := new(User)
   988  		array := g.Slice{1, 2, 3}
   989  		err := gconv.Struct(g.Map{"scores": array}, user)
   990  		t.Assert(err, nil)
   991  		t.Assert(user.Scores, array)
   992  	})
   993  	gtest.C(t, func(t *gtest.T) {
   994  		type User struct {
   995  			Scores []uint
   996  		}
   997  		user := new(User)
   998  		array := g.Slice{1, 2, 3}
   999  		err := gconv.Struct(g.Map{"scores": array}, user)
  1000  		t.Assert(err, nil)
  1001  		t.Assert(user.Scores, array)
  1002  	})
  1003  	gtest.C(t, func(t *gtest.T) {
  1004  		type User struct {
  1005  			Scores []uint32
  1006  		}
  1007  		user := new(User)
  1008  		array := g.Slice{1, 2, 3}
  1009  		err := gconv.Struct(g.Map{"scores": array}, user)
  1010  		t.Assert(err, nil)
  1011  		t.Assert(user.Scores, array)
  1012  	})
  1013  	gtest.C(t, func(t *gtest.T) {
  1014  		type User struct {
  1015  			Scores []uint64
  1016  		}
  1017  		user := new(User)
  1018  		array := g.Slice{1, 2, 3}
  1019  		err := gconv.Struct(g.Map{"scores": array}, user)
  1020  		t.Assert(err, nil)
  1021  		t.Assert(user.Scores, array)
  1022  	})
  1023  	gtest.C(t, func(t *gtest.T) {
  1024  		type User struct {
  1025  			Scores []float32
  1026  		}
  1027  		user := new(User)
  1028  		array := g.Slice{1, 2, 3}
  1029  		err := gconv.Struct(g.Map{"scores": array}, user)
  1030  		t.Assert(err, nil)
  1031  		t.Assert(user.Scores, array)
  1032  	})
  1033  	gtest.C(t, func(t *gtest.T) {
  1034  		type User struct {
  1035  			Scores []float64
  1036  		}
  1037  		user := new(User)
  1038  		array := g.Slice{1, 2, 3}
  1039  		err := gconv.Struct(g.Map{"scores": array}, user)
  1040  		t.Assert(err, nil)
  1041  		t.Assert(user.Scores, array)
  1042  	})
  1043  }
  1044  
  1045  func Test_Struct_To_Struct(t *testing.T) {
  1046  	var TestA struct {
  1047  		Id   int       `p:"id"`
  1048  		Date time.Time `p:"date"`
  1049  	}
  1050  
  1051  	var TestB struct {
  1052  		Id   int       `p:"id"`
  1053  		Date time.Time `p:"date"`
  1054  	}
  1055  	TestB.Id = 666
  1056  	TestB.Date = time.Now()
  1057  
  1058  	gtest.C(t, func(t *gtest.T) {
  1059  		t.Assert(gconv.Struct(TestB, &TestA), nil)
  1060  		t.Assert(TestA.Id, TestB.Id)
  1061  		t.Assert(TestA.Date, TestB.Date)
  1062  	})
  1063  }
  1064  
  1065  func Test_Struct_WithJson(t *testing.T) {
  1066  	type A struct {
  1067  		Name string
  1068  	}
  1069  	type B struct {
  1070  		A
  1071  		Score int
  1072  	}
  1073  	gtest.C(t, func(t *gtest.T) {
  1074  		b1 := &B{}
  1075  		b1.Name = "john"
  1076  		b1.Score = 100
  1077  		b, _ := json.Marshal(b1)
  1078  		b2 := &B{}
  1079  		err := gconv.Struct(b, b2)
  1080  		t.Assert(err, nil)
  1081  		t.Assert(b2, b1)
  1082  	})
  1083  }
  1084  
  1085  func Test_Struct_AttrStructHasTheSameTag(t *testing.T) {
  1086  	type Product struct {
  1087  		Id              int       `json:"id"`
  1088  		UpdatedAt       time.Time `json:"-" `
  1089  		UpdatedAtFormat string    `json:"updated_at" `
  1090  	}
  1091  
  1092  	type Order struct {
  1093  		Id        int       `json:"id"`
  1094  		UpdatedAt time.Time `json:"updated_at"`
  1095  		Product   Product   `json:"products"`
  1096  	}
  1097  	gtest.C(t, func(t *gtest.T) {
  1098  		data := g.Map{
  1099  			"id":         1,
  1100  			"updated_at": time.Now(),
  1101  		}
  1102  		order := new(Order)
  1103  		err := gconv.Struct(data, order)
  1104  		t.Assert(err, nil)
  1105  		t.Assert(order.Id, data["id"])
  1106  		t.Assert(order.UpdatedAt, data["updated_at"])
  1107  		t.Assert(order.Product.Id, 0)
  1108  		t.Assert(order.Product.UpdatedAt.IsZero(), true)
  1109  		t.Assert(order.Product.UpdatedAtFormat, "")
  1110  	})
  1111  }
  1112  
  1113  func Test_Struct_DirectReflectSet(t *testing.T) {
  1114  	type A struct {
  1115  		Id   int
  1116  		Name string
  1117  	}
  1118  
  1119  	gtest.C(t, func(t *gtest.T) {
  1120  		var (
  1121  			a = &A{
  1122  				Id:   1,
  1123  				Name: "john",
  1124  			}
  1125  			b *A
  1126  		)
  1127  		err := gconv.Struct(a, &b)
  1128  		t.Assert(err, nil)
  1129  		t.AssertEQ(a, b)
  1130  	})
  1131  	gtest.C(t, func(t *gtest.T) {
  1132  		var (
  1133  			a = A{
  1134  				Id:   1,
  1135  				Name: "john",
  1136  			}
  1137  			b A
  1138  		)
  1139  		err := gconv.Struct(a, &b)
  1140  		t.Assert(err, nil)
  1141  		t.AssertEQ(a, b)
  1142  	})
  1143  }
  1144  
  1145  func Test_Struct_NilEmbeddedStructAttribute(t *testing.T) {
  1146  	type A struct {
  1147  		Name string
  1148  	}
  1149  	type B struct {
  1150  		*A
  1151  		Id int
  1152  	}
  1153  
  1154  	gtest.C(t, func(t *gtest.T) {
  1155  		var (
  1156  			b *B
  1157  		)
  1158  		err := gconv.Struct(g.Map{
  1159  			"id":   1,
  1160  			"name": nil,
  1161  		}, &b)
  1162  		t.Assert(err, nil)
  1163  		t.Assert(b.Id, 1)
  1164  		t.Assert(b.Name, "")
  1165  	})
  1166  }
  1167  
  1168  func Test_Struct_JsonParam(t *testing.T) {
  1169  	type A struct {
  1170  		Id   int    `json:"id"`
  1171  		Name string `json:"name"`
  1172  	}
  1173  	// struct
  1174  	gtest.C(t, func(t *gtest.T) {
  1175  		var a = A{}
  1176  		err := gconv.Struct([]byte(`{"id":1,"name":"john"}`), &a)
  1177  		t.Assert(err, nil)
  1178  		t.Assert(a.Id, 1)
  1179  		t.Assert(a.Name, "john")
  1180  	})
  1181  	// *struct
  1182  	gtest.C(t, func(t *gtest.T) {
  1183  		var a = &A{}
  1184  		err := gconv.Struct([]byte(`{"id":1,"name":"john"}`), a)
  1185  		t.Assert(err, nil)
  1186  		t.Assert(a.Id, 1)
  1187  		t.Assert(a.Name, "john")
  1188  	})
  1189  	// *struct nil
  1190  	gtest.C(t, func(t *gtest.T) {
  1191  		var a *A
  1192  		err := gconv.Struct([]byte(`{"id":1,"name":"john"}`), &a)
  1193  		t.Assert(err, nil)
  1194  		t.Assert(a.Id, 1)
  1195  		t.Assert(a.Name, "john")
  1196  	})
  1197  }
  1198  
  1199  func Test_Struct_GVarAttribute(t *testing.T) {
  1200  	type A struct {
  1201  		Id     int    `json:"id"`
  1202  		Name   string `json:"name"`
  1203  		Status bool   `json:"status"`
  1204  	}
  1205  	gtest.C(t, func(t *gtest.T) {
  1206  		var (
  1207  			a    = A{}
  1208  			data = g.Map{
  1209  				"id":     100,
  1210  				"name":   "john",
  1211  				"status": gvar.New(false),
  1212  			}
  1213  		)
  1214  		err := gconv.Struct(data, &a)
  1215  		t.Assert(err, nil)
  1216  		t.Assert(a.Id, data["id"])
  1217  		t.Assert(a.Name, data["name"])
  1218  		t.Assert(a.Status, data["status"])
  1219  	})
  1220  
  1221  }
  1222  
  1223  func Test_Struct_MapAttribute(t *testing.T) {
  1224  	type NodeStatus struct {
  1225  		ID int
  1226  	}
  1227  	type Nodes map[string]NodeStatus
  1228  	type Output struct {
  1229  		Nodes Nodes
  1230  	}
  1231  
  1232  	gtest.C(t, func(t *gtest.T) {
  1233  		var (
  1234  			out  = Output{}
  1235  			data = g.Map{
  1236  				"nodes": g.Map{
  1237  					"name": g.Map{
  1238  						"id": 10000,
  1239  					},
  1240  				},
  1241  			}
  1242  		)
  1243  		err := gconv.Struct(data, &out)
  1244  		t.AssertNil(err)
  1245  	})
  1246  }