github.com/zhongdalu/gf@v1.0.0/g/util/gconv/gconv_z_unit_struct_test.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  
     7  package gconv_test
     8  
     9  import (
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/zhongdalu/gf/g"
    14  	"github.com/zhongdalu/gf/g/os/gtime"
    15  	"github.com/zhongdalu/gf/g/test/gtest"
    16  	"github.com/zhongdalu/gf/g/util/gconv"
    17  )
    18  
    19  func Test_Struct_Basic1(t *testing.T) {
    20  	gtest.Case(t, func() {
    21  		type User struct {
    22  			Uid      int
    23  			Name     string
    24  			Site_Url string
    25  			NickName string
    26  			Pass1    string `gconv:"password1"`
    27  			Pass2    string `gconv:"password2"`
    28  		}
    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  			gtest.Error(err)
    41  		}
    42  		gtest.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  		// 使用struct tag映射绑定属性值到对象
    52  		user = new(User)
    53  		params2 := g.Map{
    54  			"uid":       2,
    55  			"name":      "smith",
    56  			"site-url":  "https://goframe.org",
    57  			"nick name": "johng",
    58  			"password1": "111",
    59  			"password2": "222",
    60  		}
    61  		if err := gconv.Struct(params2, user); err != nil {
    62  			gtest.Error(err)
    63  		}
    64  		gtest.Assert(user, &User{
    65  			Uid:      2,
    66  			Name:     "smith",
    67  			Site_Url: "https://goframe.org",
    68  			NickName: "johng",
    69  			Pass1:    "111",
    70  			Pass2:    "222",
    71  		})
    72  	})
    73  }
    74  
    75  // 使用默认映射规则绑定属性值到对象
    76  func Test_Struct_Basic2(t *testing.T) {
    77  	gtest.Case(t, func() {
    78  		type User struct {
    79  			Uid     int
    80  			Name    string
    81  			SiteUrl string
    82  			Pass1   string
    83  			Pass2   string
    84  		}
    85  		user := new(User)
    86  		params := g.Map{
    87  			"uid":      1,
    88  			"Name":     "john",
    89  			"site_url": "https://goframe.org",
    90  			"PASS1":    "123",
    91  			"PASS2":    "456",
    92  		}
    93  		if err := gconv.Struct(params, user); err != nil {
    94  			gtest.Error(err)
    95  		}
    96  		gtest.Assert(user, &User{
    97  			Uid:     1,
    98  			Name:    "john",
    99  			SiteUrl: "https://goframe.org",
   100  			Pass1:   "123",
   101  			Pass2:   "456",
   102  		})
   103  	})
   104  }
   105  
   106  // 带有指针的基础类型属性
   107  func Test_Struct_Basic3(t *testing.T) {
   108  	gtest.Case(t, func() {
   109  		type User struct {
   110  			Uid  int
   111  			Name *string
   112  		}
   113  		user := new(User)
   114  		params := g.Map{
   115  			"uid":  1,
   116  			"Name": "john",
   117  		}
   118  		if err := gconv.Struct(params, user); err != nil {
   119  			gtest.Error(err)
   120  		}
   121  		gtest.Assert(user.Uid, 1)
   122  		gtest.Assert(*user.Name, "john")
   123  	})
   124  }
   125  
   126  // slice类型属性的赋值
   127  func Test_Struct_Attr_Slice(t *testing.T) {
   128  	gtest.Case(t, func() {
   129  		type User struct {
   130  			Scores []int
   131  		}
   132  		scores := []interface{}{99, 100, 60, 140}
   133  		user := new(User)
   134  		if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil {
   135  			gtest.Error(err)
   136  		} else {
   137  			gtest.Assert(user, &User{
   138  				Scores: []int{99, 100, 60, 140},
   139  			})
   140  		}
   141  	})
   142  }
   143  
   144  // 属性为struct对象
   145  func Test_Struct_Attr_Struct(t *testing.T) {
   146  	gtest.Case(t, func() {
   147  		type Score struct {
   148  			Name   string
   149  			Result int
   150  		}
   151  		type User struct {
   152  			Scores Score
   153  		}
   154  
   155  		user := new(User)
   156  		scores := map[string]interface{}{
   157  			"Scores": map[string]interface{}{
   158  				"Name":   "john",
   159  				"Result": 100,
   160  			},
   161  		}
   162  
   163  		// 嵌套struct转换
   164  		if err := gconv.Struct(scores, user); err != nil {
   165  			gtest.Error(err)
   166  		} else {
   167  			gtest.Assert(user, &User{
   168  				Scores: Score{
   169  					Name:   "john",
   170  					Result: 100,
   171  				},
   172  			})
   173  		}
   174  	})
   175  }
   176  
   177  // 属性为struct对象指针
   178  func Test_Struct_Attr_Struct_Ptr(t *testing.T) {
   179  	gtest.Case(t, func() {
   180  		type Score struct {
   181  			Name   string
   182  			Result int
   183  		}
   184  		type User struct {
   185  			Scores *Score
   186  		}
   187  
   188  		user := new(User)
   189  		scores := map[string]interface{}{
   190  			"Scores": map[string]interface{}{
   191  				"Name":   "john",
   192  				"Result": 100,
   193  			},
   194  		}
   195  
   196  		// 嵌套struct转换
   197  		if err := gconv.Struct(scores, user); err != nil {
   198  			gtest.Error(err)
   199  		} else {
   200  			gtest.Assert(user.Scores, &Score{
   201  				Name:   "john",
   202  				Result: 100,
   203  			})
   204  		}
   205  	})
   206  }
   207  
   208  // 属性为struct对象slice
   209  func Test_Struct_Attr_Struct_Slice1(t *testing.T) {
   210  	gtest.Case(t, func() {
   211  		type Score struct {
   212  			Name   string
   213  			Result int
   214  		}
   215  		type User struct {
   216  			Scores []Score
   217  		}
   218  
   219  		user := new(User)
   220  		scores := map[string]interface{}{
   221  			"Scores": map[string]interface{}{
   222  				"Name":   "john",
   223  				"Result": 100,
   224  			},
   225  		}
   226  
   227  		// 嵌套struct转换,属性为slice类型,数值为map类型
   228  		if err := gconv.Struct(scores, user); err != nil {
   229  			gtest.Error(err)
   230  		} else {
   231  			gtest.Assert(user.Scores, []Score{
   232  				{
   233  					Name:   "john",
   234  					Result: 100,
   235  				},
   236  			})
   237  		}
   238  	})
   239  }
   240  
   241  // 属性为struct对象slice
   242  func Test_Struct_Attr_Struct_Slice2(t *testing.T) {
   243  	gtest.Case(t, func() {
   244  		type Score struct {
   245  			Name   string
   246  			Result int
   247  		}
   248  		type User struct {
   249  			Scores []Score
   250  		}
   251  
   252  		user := new(User)
   253  		scores := map[string]interface{}{
   254  			"Scores": []interface{}{
   255  				map[string]interface{}{
   256  					"Name":   "john",
   257  					"Result": 100,
   258  				},
   259  				map[string]interface{}{
   260  					"Name":   "smith",
   261  					"Result": 60,
   262  				},
   263  			},
   264  		}
   265  
   266  		// 嵌套struct转换,属性为slice类型,数值为slice map类型
   267  		if err := gconv.Struct(scores, user); err != nil {
   268  			gtest.Error(err)
   269  		} else {
   270  			gtest.Assert(user.Scores, []Score{
   271  				{
   272  					Name:   "john",
   273  					Result: 100,
   274  				},
   275  				{
   276  					Name:   "smith",
   277  					Result: 60,
   278  				},
   279  			})
   280  		}
   281  	})
   282  }
   283  
   284  // 属性为struct对象slice ptr
   285  func Test_Struct_Attr_Struct_Slice_Ptr(t *testing.T) {
   286  	gtest.Case(t, func() {
   287  		type Score struct {
   288  			Name   string
   289  			Result int
   290  		}
   291  		type User struct {
   292  			Scores []*Score
   293  		}
   294  
   295  		user := new(User)
   296  		scores := map[string]interface{}{
   297  			"Scores": []interface{}{
   298  				map[string]interface{}{
   299  					"Name":   "john",
   300  					"Result": 100,
   301  				},
   302  				map[string]interface{}{
   303  					"Name":   "smith",
   304  					"Result": 60,
   305  				},
   306  			},
   307  		}
   308  
   309  		// 嵌套struct转换,属性为slice类型,数值为slice map类型
   310  		if err := gconv.Struct(scores, user); err != nil {
   311  			gtest.Error(err)
   312  		} else {
   313  			gtest.Assert(len(user.Scores), 2)
   314  			gtest.Assert(user.Scores[0], &Score{
   315  				Name:   "john",
   316  				Result: 100,
   317  			})
   318  			gtest.Assert(user.Scores[1], &Score{
   319  				Name:   "smith",
   320  				Result: 60,
   321  			})
   322  		}
   323  	})
   324  }
   325  
   326  func Test_Struct_PrivateAttribute(t *testing.T) {
   327  	type User struct {
   328  		Id   int
   329  		name string
   330  	}
   331  	gtest.Case(t, func() {
   332  		user := new(User)
   333  		err := gconv.Struct(g.Map{"id": 1, "name": "john"}, user)
   334  		gtest.Assert(err, nil)
   335  		gtest.Assert(user.Id, 1)
   336  		gtest.Assert(user.name, "")
   337  	})
   338  }
   339  
   340  func Test_Struct_Deep(t *testing.T) {
   341  
   342  	gtest.Case(t, func() {
   343  		type Base struct {
   344  			Age int
   345  		}
   346  		type User struct {
   347  			Id   int
   348  			Name string
   349  			Base
   350  		}
   351  		user := new(User)
   352  		params := g.Map{
   353  			"id":   1,
   354  			"name": "john",
   355  			"age":  18,
   356  		}
   357  		err := gconv.StructDeep(params, user)
   358  		gtest.Assert(err, nil)
   359  		gtest.Assert(user.Id, params["id"])
   360  		gtest.Assert(user.Name, params["name"])
   361  		gtest.Assert(user.Age, params["age"])
   362  	})
   363  
   364  	gtest.Case(t, func() {
   365  		type Ids struct {
   366  			Id  int `json:"id"`
   367  			Uid int `json:"uid"`
   368  		}
   369  		type Base struct {
   370  			Ids
   371  			CreateTime string `json:"create_time"`
   372  		}
   373  		type User struct {
   374  			Base
   375  			Passport string `json:"passport"`
   376  			Password string `json:"password"`
   377  			Nickname string `json:"nickname"`
   378  		}
   379  		data := g.Map{
   380  			"id":          100,
   381  			"uid":         101,
   382  			"passport":    "t1",
   383  			"password":    "123456",
   384  			"nickname":    "T1",
   385  			"create_time": "2019",
   386  		}
   387  		user := new(User)
   388  		err := gconv.StructDeep(data, user)
   389  		gtest.Assert(err, nil)
   390  		gtest.Assert(user.Id, 100)
   391  		gtest.Assert(user.Uid, 101)
   392  		gtest.Assert(user.Nickname, "T1")
   393  		gtest.Assert(user.CreateTime, "2019")
   394  	})
   395  }
   396  
   397  func Test_Struct_Time(t *testing.T) {
   398  	gtest.Case(t, func() {
   399  		type User struct {
   400  			CreateTime time.Time
   401  		}
   402  		now := time.Now()
   403  		user := new(User)
   404  		gconv.Struct(g.Map{
   405  			"create_time": now,
   406  		}, user)
   407  		gtest.Assert(user.CreateTime.UTC().String(), now.UTC().String())
   408  	})
   409  
   410  	gtest.Case(t, func() {
   411  		type User struct {
   412  			CreateTime *time.Time
   413  		}
   414  		now := time.Now()
   415  		user := new(User)
   416  		gconv.Struct(g.Map{
   417  			"create_time": &now,
   418  		}, user)
   419  		gtest.Assert(user.CreateTime.UTC().String(), now.UTC().String())
   420  	})
   421  
   422  	gtest.Case(t, func() {
   423  		type User struct {
   424  			CreateTime *gtime.Time
   425  		}
   426  		now := time.Now()
   427  		user := new(User)
   428  		gconv.Struct(g.Map{
   429  			"create_time": &now,
   430  		}, user)
   431  		gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   432  	})
   433  
   434  	gtest.Case(t, func() {
   435  		type User struct {
   436  			CreateTime gtime.Time
   437  		}
   438  		now := time.Now()
   439  		user := new(User)
   440  		gconv.Struct(g.Map{
   441  			"create_time": &now,
   442  		}, user)
   443  		gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   444  	})
   445  
   446  	gtest.Case(t, func() {
   447  		type User struct {
   448  			CreateTime gtime.Time
   449  		}
   450  		now := time.Now()
   451  		user := new(User)
   452  		gconv.Struct(g.Map{
   453  			"create_time": now,
   454  		}, user)
   455  		gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
   456  	})
   457  }
   458  
   459  // Auto create struct when given pointer.
   460  func Test_Struct_Create(t *testing.T) {
   461  	gtest.Case(t, func() {
   462  		type User struct {
   463  			Uid  int
   464  			Name string
   465  		}
   466  		user := (*User)(nil)
   467  		params := g.Map{
   468  			"uid":  1,
   469  			"Name": "john",
   470  		}
   471  		err := gconv.Struct(params, &user)
   472  		gtest.Assert(err, nil)
   473  		gtest.Assert(user.Uid, 1)
   474  		gtest.Assert(user.Name, "john")
   475  	})
   476  
   477  	gtest.Case(t, func() {
   478  		type User struct {
   479  			Uid  int
   480  			Name string
   481  		}
   482  		user := (*User)(nil)
   483  		params := g.Map{
   484  			"uid":  1,
   485  			"Name": "john",
   486  		}
   487  		err := gconv.Struct(params, user)
   488  		gtest.AssertNE(err, nil)
   489  		gtest.Assert(user, nil)
   490  	})
   491  
   492  }