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