github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_z_unit_issue_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 "fmt" 11 "math/big" 12 "testing" 13 "time" 14 15 "github.com/gogf/gf/v2/container/gtype" 16 "github.com/gogf/gf/v2/encoding/gjson" 17 "github.com/gogf/gf/v2/frame/g" 18 "github.com/gogf/gf/v2/internal/json" 19 "github.com/gogf/gf/v2/os/gtime" 20 "github.com/gogf/gf/v2/test/gtest" 21 "github.com/gogf/gf/v2/util/gconv" 22 ) 23 24 // https://github.com/gogf/gf/issues/1227 25 func Test_Issue1227(t *testing.T) { 26 gtest.C(t, func(t *gtest.T) { 27 type StructFromIssue1227 struct { 28 Name string `json:"n1"` 29 } 30 tests := []struct { 31 name string 32 origin interface{} 33 want string 34 }{ 35 { 36 name: "Case1", 37 origin: `{"n1":"n1"}`, 38 want: "n1", 39 }, 40 { 41 name: "Case2", 42 origin: `{"name":"name"}`, 43 want: "", 44 }, 45 { 46 name: "Case3", 47 origin: `{"NaMe":"NaMe"}`, 48 want: "", 49 }, 50 { 51 name: "Case4", 52 origin: g.Map{"n1": "n1"}, 53 want: "n1", 54 }, 55 { 56 name: "Case5", 57 origin: g.Map{"NaMe": "n1"}, 58 want: "n1", 59 }, 60 } 61 for _, tt := range tests { 62 p := StructFromIssue1227{} 63 if err := gconv.Struct(tt.origin, &p); err != nil { 64 t.Error(err) 65 } 66 t.Assert(p.Name, tt.want) 67 } 68 }) 69 70 // Chinese key. 71 gtest.C(t, func(t *gtest.T) { 72 type StructFromIssue1227 struct { 73 Name string `json:"中文Key"` 74 } 75 tests := []struct { 76 name string 77 origin interface{} 78 want string 79 }{ 80 { 81 name: "Case1", 82 origin: `{"中文Key":"n1"}`, 83 want: "n1", 84 }, 85 { 86 name: "Case2", 87 origin: `{"Key":"name"}`, 88 want: "", 89 }, 90 { 91 name: "Case3", 92 origin: `{"NaMe":"NaMe"}`, 93 want: "", 94 }, 95 { 96 name: "Case4", 97 origin: g.Map{"中文Key": "n1"}, 98 want: "n1", 99 }, 100 { 101 name: "Case5", 102 origin: g.Map{"中文KEY": "n1"}, 103 want: "", 104 }, 105 { 106 name: "Case5", 107 origin: g.Map{"KEY": "n1"}, 108 want: "", 109 }, 110 } 111 for _, tt := range tests { 112 p := StructFromIssue1227{} 113 if err := gconv.Struct(tt.origin, &p); err != nil { 114 t.Error(err) 115 } 116 //t.Log(tt) 117 t.Assert(p.Name, tt.want) 118 } 119 }) 120 } 121 122 // https://github.com/gogf/gf/issues/1607 123 type issue1607Float64 float64 124 125 func (f *issue1607Float64) UnmarshalValue(value interface{}) error { 126 if v, ok := value.(*big.Rat); ok { 127 f64, _ := v.Float64() 128 *f = issue1607Float64(f64) 129 } 130 return nil 131 } 132 133 func Test_Issue1607(t *testing.T) { 134 gtest.C(t, func(t *gtest.T) { 135 type Demo struct { 136 B issue1607Float64 137 } 138 rat := &big.Rat{} 139 rat.SetFloat64(1.5) 140 141 var demos = make([]Demo, 1) 142 err := gconv.Scan([]map[string]interface{}{ 143 {"A": 1, "B": rat}, 144 }, &demos) 145 t.AssertNil(err) 146 t.Assert(demos[0].B, 1.5) 147 }) 148 } 149 150 // https://github.com/gogf/gf/issues/1946 151 func Test_Issue1946(t *testing.T) { 152 gtest.C(t, func(t *gtest.T) { 153 type B struct { 154 init *gtype.Bool 155 Name string 156 } 157 type A struct { 158 B *B 159 } 160 a := &A{ 161 B: &B{ 162 init: gtype.NewBool(true), 163 }, 164 } 165 err := gconv.Struct(g.Map{ 166 "B": g.Map{ 167 "Name": "init", 168 }, 169 }, a) 170 t.AssertNil(err) 171 t.Assert(a.B.Name, "init") 172 t.Assert(a.B.init.Val(), true) 173 }) 174 // It cannot change private attribute. 175 gtest.C(t, func(t *gtest.T) { 176 type B struct { 177 init *gtype.Bool 178 Name string 179 } 180 type A struct { 181 B *B 182 } 183 a := &A{ 184 B: &B{ 185 init: gtype.NewBool(true), 186 }, 187 } 188 err := gconv.Struct(g.Map{ 189 "B": g.Map{ 190 "init": 0, 191 "Name": "init", 192 }, 193 }, a) 194 t.AssertNil(err) 195 t.Assert(a.B.Name, "init") 196 t.Assert(a.B.init.Val(), true) 197 }) 198 // It can change public attribute. 199 gtest.C(t, func(t *gtest.T) { 200 type B struct { 201 Init *gtype.Bool 202 Name string 203 } 204 type A struct { 205 B *B 206 } 207 a := &A{ 208 B: &B{ 209 Init: gtype.NewBool(), 210 }, 211 } 212 err := gconv.Struct(g.Map{ 213 "B": g.Map{ 214 "Init": 1, 215 "Name": "init", 216 }, 217 }, a) 218 t.AssertNil(err) 219 t.Assert(a.B.Name, "init") 220 t.Assert(a.B.Init.Val(), true) 221 }) 222 } 223 224 // https://github.com/gogf/gf/issues/2381 225 func Test_Issue2381(t *testing.T) { 226 gtest.C(t, func(t *gtest.T) { 227 type Inherit struct { 228 Id int64 `json:"id" description:"Id"` 229 Flag *gjson.Json `json:"flag" description:"标签"` 230 Title string `json:"title" description:"标题"` 231 CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 232 } 233 type Test1 struct { 234 Inherit 235 } 236 type Test2 struct { 237 Inherit 238 } 239 var ( 240 a1 Test1 241 a2 Test2 242 ) 243 244 a1 = Test1{ 245 Inherit{ 246 Id: 2, 247 Flag: gjson.New("[1, 2]"), 248 Title: "测试", 249 CreatedAt: gtime.Now(), 250 }, 251 } 252 err := gconv.Scan(a1, &a2) 253 t.AssertNil(err) 254 t.Assert(a1.Id, a2.Id) 255 t.Assert(a1.Title, a2.Title) 256 t.Assert(a1.CreatedAt, a2.CreatedAt) 257 t.Assert(a1.Flag.String(), a2.Flag.String()) 258 }) 259 } 260 261 // https://github.com/gogf/gf/issues/2391 262 func Test_Issue2391(t *testing.T) { 263 gtest.C(t, func(t *gtest.T) { 264 type Inherit struct { 265 Ids []int 266 Ids2 []int64 267 Flag *gjson.Json 268 Title string 269 } 270 271 type Test1 struct { 272 Inherit 273 } 274 type Test2 struct { 275 Inherit 276 } 277 278 var ( 279 a1 Test1 280 a2 Test2 281 ) 282 283 a1 = Test1{ 284 Inherit{ 285 Ids: []int{1, 2, 3}, 286 Ids2: []int64{4, 5, 6}, 287 Flag: gjson.New("[\"1\", \"2\"]"), 288 Title: "测试", 289 }, 290 } 291 292 err := gconv.Scan(a1, &a2) 293 t.AssertNil(err) 294 t.Assert(a1.Ids, a2.Ids) 295 t.Assert(a1.Ids2, a2.Ids2) 296 t.Assert(a1.Title, a2.Title) 297 t.Assert(a1.Flag.String(), a2.Flag.String()) 298 }) 299 } 300 301 // https://github.com/gogf/gf/issues/2395 302 func Test_Issue2395(t *testing.T) { 303 gtest.C(t, func(t *gtest.T) { 304 type Test struct { 305 Num int 306 } 307 var () 308 obj := Test{Num: 0} 309 t.Assert(gconv.Interfaces(obj), []interface{}{obj}) 310 }) 311 } 312 313 // https://github.com/gogf/gf/issues/2371 314 func Test_Issue2371(t *testing.T) { 315 gtest.C(t, func(t *gtest.T) { 316 var ( 317 s = struct { 318 Time time.Time `json:"time"` 319 }{} 320 jsonMap = map[string]interface{}{"time": "2022-12-15 16:11:34"} 321 ) 322 323 err := gconv.Struct(jsonMap, &s) 324 t.AssertNil(err) 325 t.Assert(s.Time.UTC(), `2022-12-15 08:11:34 +0000 UTC`) 326 }) 327 } 328 329 // https://github.com/gogf/gf/issues/2901 330 func Test_Issue2901(t *testing.T) { 331 type GameApp2 struct { 332 ForceUpdateTime *time.Time 333 } 334 gtest.C(t, func(t *gtest.T) { 335 src := map[string]interface{}{ 336 "FORCE_UPDATE_TIME": time.Now(), 337 } 338 m := GameApp2{} 339 err := gconv.Scan(src, &m) 340 t.AssertNil(err) 341 }) 342 } 343 344 // https://github.com/gogf/gf/issues/3006 345 func Test_Issue3006(t *testing.T) { 346 type tFF struct { 347 Val1 json.RawMessage `json:"val1"` 348 Val2 []json.RawMessage `json:"val2"` 349 Val3 map[string]json.RawMessage `json:"val3"` 350 } 351 352 gtest.C(t, func(t *gtest.T) { 353 ff := &tFF{} 354 var tmp = map[string]any{ 355 "val1": map[string]any{"hello": "world"}, 356 "val2": []any{map[string]string{"hello": "world"}}, 357 "val3": map[string]map[string]string{"val3": {"hello": "world"}}, 358 } 359 360 err := gconv.Struct(tmp, ff) 361 t.AssertNil(err) 362 t.AssertNE(ff, nil) 363 t.Assert(ff.Val1, []byte(`{"hello":"world"}`)) 364 t.AssertEQ(len(ff.Val2), 1) 365 t.Assert(ff.Val2[0], []byte(`{"hello":"world"}`)) 366 t.AssertEQ(len(ff.Val3), 1) 367 t.Assert(ff.Val3["val3"], []byte(`{"hello":"world"}`)) 368 }) 369 } 370 371 // https://github.com/gogf/gf/issues/3731 372 func Test_Issue3731(t *testing.T) { 373 type Data struct { 374 Doc map[string]interface{} `json:"doc"` 375 } 376 377 gtest.C(t, func(t *gtest.T) { 378 dataMap := map[string]any{ 379 "doc": map[string]any{ 380 "craft": nil, 381 }, 382 } 383 384 var args Data 385 err := gconv.Struct(dataMap, &args) 386 t.AssertNil(err) 387 t.AssertEQ("<nil>", fmt.Sprintf("%T", args.Doc["craft"])) 388 }) 389 } 390 391 // https://github.com/gogf/gf/issues/3764 392 func Test_Issue3764(t *testing.T) { 393 type T struct { 394 True bool `json:"true"` 395 False bool `json:"false"` 396 TruePtr *bool `json:"true_ptr"` 397 FalsePtr *bool `json:"false_ptr"` 398 } 399 gtest.C(t, func(t *gtest.T) { 400 trueValue := true 401 falseValue := false 402 m := g.Map{ 403 "true": trueValue, 404 "false": falseValue, 405 "true_ptr": &trueValue, 406 "false_ptr": &falseValue, 407 } 408 tt := &T{} 409 err := gconv.Struct(m, &tt) 410 t.AssertNil(err) 411 t.AssertEQ(tt.True, true) 412 t.AssertEQ(tt.False, false) 413 t.AssertEQ(*tt.TruePtr, trueValue) 414 t.AssertEQ(*tt.FalsePtr, falseValue) 415 }) 416 } 417 418 // https://github.com/gogf/gf/issues/3789 419 func Test_Issue3789(t *testing.T) { 420 type ItemSecondThird struct { 421 SecondID uint64 `json:"secondId,string"` 422 ThirdID uint64 `json:"thirdId,string"` 423 } 424 type ItemFirst struct { 425 ID uint64 `json:"id,string"` 426 ItemSecondThird 427 } 428 type ItemInput struct { 429 ItemFirst 430 } 431 type HelloReq struct { 432 g.Meta `path:"/hello" method:"GET"` 433 ItemInput 434 } 435 gtest.C(t, func(t *gtest.T) { 436 m := map[string]interface{}{ 437 "id": 1, 438 "secondId": 2, 439 "thirdId": 3, 440 } 441 var dest HelloReq 442 err := gconv.Scan(m, &dest) 443 t.AssertNil(err) 444 t.Assert(dest.ID, uint64(1)) 445 t.Assert(dest.SecondID, uint64(2)) 446 t.Assert(dest.ThirdID, uint64(3)) 447 }) 448 } 449 450 // https://github.com/gogf/gf/issues/3797 451 func Test_Issue3797(t *testing.T) { 452 type Option struct { 453 F1 int 454 F2 string 455 } 456 type Rule struct { 457 ID int64 `json:"id"` 458 Rule []*Option `json:"rule"` 459 } 460 type Res1 struct { 461 g.Meta 462 Rule 463 } 464 gtest.C(t, func(t *gtest.T) { 465 var r = &Rule{ 466 ID: 100, 467 } 468 var res = &Res1{} 469 for i := 0; i < 10000; i++ { 470 err := gconv.Scan(r, res) 471 t.AssertNil(err) 472 t.Assert(res.ID, 100) 473 t.AssertEQ(res.Rule.Rule, nil) 474 } 475 }) 476 } 477 478 // https://github.com/gogf/gf/issues/3800 479 func Test_Issue3800(t *testing.T) { 480 // might be random assignment in converting, 481 // it here so runs multiple times to reproduce the issue. 482 for i := 0; i < 1000; i++ { 483 doTestIssue3800(t) 484 } 485 } 486 487 func doTestIssue3800(t *testing.T) { 488 type NullID string 489 490 type StructA struct { 491 Superior string `json:"superior"` 492 UpdatedTick int `json:"updated_tick"` 493 } 494 type StructB struct { 495 Superior *NullID `json:"superior"` 496 UpdatedTick *int `json:"updated_tick"` 497 } 498 499 type StructC struct { 500 Superior string `json:"superior"` 501 UpdatedTick int `json:"updated_tick"` 502 } 503 type StructD struct { 504 StructC 505 Superior *NullID `json:"superior"` 506 UpdatedTick *int `json:"updated_tick"` 507 } 508 509 type StructE struct { 510 Superior string `json:"superior"` 511 UpdatedTick int `json:"updated_tick"` 512 } 513 type StructF struct { 514 Superior *NullID `json:"superior"` 515 UpdatedTick *int `json:"updated_tick"` 516 StructE 517 } 518 519 type StructG struct { 520 Superior string `json:"superior"` 521 UpdatedTick int `json:"updated_tick"` 522 } 523 type StructH struct { 524 Superior *string `json:"superior"` 525 UpdatedTick *int `json:"updated_tick"` 526 StructG 527 } 528 529 type StructI struct { 530 Master struct { 531 Superior *NullID `json:"superior"` 532 UpdatedTick int `json:"updated_tick"` 533 } `json:"master"` 534 } 535 type StructJ struct { 536 StructA 537 Superior *NullID `json:"superior"` 538 UpdatedTick *int `json:"updated_tick"` 539 } 540 541 type StructK struct { 542 Master struct { 543 Superior *NullID `json:"superior"` 544 UpdatedTick int `json:"updated_tick"` 545 } `json:"master"` 546 } 547 type StructL struct { 548 Superior *NullID `json:"superior"` 549 UpdatedTick *int `json:"updated_tick"` 550 StructA 551 } 552 553 // case 0 554 // NullID should not be initialized. 555 gtest.C(t, func(t *gtest.T) { 556 structA := g.Map{ 557 "UpdatedTick": 10, 558 } 559 structB := StructB{} 560 err := gconv.Scan(structA, &structB) 561 t.AssertNil(err) 562 t.AssertNil(structB.Superior) 563 t.Assert(*structB.UpdatedTick, structA["UpdatedTick"]) 564 }) 565 566 // case 1 567 gtest.C(t, func(t *gtest.T) { 568 structA := StructA{ 569 Superior: "superior100", 570 UpdatedTick: 20, 571 } 572 structB := StructB{} 573 err := gconv.Scan(structA, &structB) 574 t.AssertNil(err) 575 t.Assert(*structB.Superior, structA.Superior) 576 }) 577 578 // case 2 579 gtest.C(t, func(t *gtest.T) { 580 structA1 := StructA{ 581 Superior: "100", 582 UpdatedTick: 20, 583 } 584 structB1 := StructB{} 585 err := gconv.Scan(structA1, &structB1) 586 t.AssertNil(err) 587 t.Assert(*structB1.Superior, structA1.Superior) 588 t.Assert(*structB1.UpdatedTick, structA1.UpdatedTick) 589 }) 590 591 // case 3 592 gtest.C(t, func(t *gtest.T) { 593 structC := StructC{ 594 Superior: "superior100", 595 UpdatedTick: 20, 596 } 597 structD := StructD{} 598 err := gconv.Scan(structC, &structD) 599 t.AssertNil(err) 600 t.Assert(structD.StructC.Superior, structC.Superior) 601 t.Assert(*structD.Superior, structC.Superior) 602 t.Assert(*structD.UpdatedTick, structC.UpdatedTick) 603 }) 604 605 // case 4 606 gtest.C(t, func(t *gtest.T) { 607 structC1 := StructC{ 608 Superior: "100", 609 UpdatedTick: 20, 610 } 611 structD1 := StructD{} 612 err := gconv.Scan(structC1, &structD1) 613 t.AssertNil(err) 614 t.Assert(structD1.StructC.Superior, structC1.Superior) 615 t.Assert(structD1.StructC.UpdatedTick, structC1.UpdatedTick) 616 t.Assert(*structD1.Superior, structC1.Superior) 617 t.Assert(*structD1.UpdatedTick, structC1.UpdatedTick) 618 }) 619 620 // case 5 621 gtest.C(t, func(t *gtest.T) { 622 structE := StructE{ 623 Superior: "superior100", 624 UpdatedTick: 20, 625 } 626 structF := StructF{} 627 err := gconv.Scan(structE, &structF) 628 t.AssertNil(err) 629 t.Assert(structF.StructE.Superior, structE.Superior) 630 t.Assert(structF.StructE.UpdatedTick, structE.UpdatedTick) 631 t.Assert(*structF.Superior, structE.Superior) 632 t.Assert(*structF.UpdatedTick, structE.UpdatedTick) 633 }) 634 635 // case 6 636 gtest.C(t, func(t *gtest.T) { 637 structE1 := StructE{ 638 Superior: "100", 639 UpdatedTick: 20, 640 } 641 structF1 := StructF{} 642 err := gconv.Scan(structE1, &structF1) 643 t.AssertNil(err) 644 t.Assert(*structF1.Superior, structE1.Superior) 645 t.Assert(*structF1.UpdatedTick, structE1.UpdatedTick) 646 t.Assert(structF1.StructE.Superior, structE1.Superior) 647 t.Assert(structF1.StructE.UpdatedTick, structE1.UpdatedTick) 648 }) 649 650 // case 7 651 gtest.C(t, func(t *gtest.T) { 652 structG := StructG{ 653 Superior: "superior100", 654 UpdatedTick: 20, 655 } 656 structH := StructH{} 657 err := gconv.Scan(structG, &structH) 658 t.AssertNil(err) 659 t.Assert(*structH.Superior, structG.Superior) 660 t.Assert(*structH.UpdatedTick, structG.UpdatedTick) 661 t.Assert(structH.StructG.Superior, structG.Superior) 662 t.Assert(structH.StructG.UpdatedTick, structG.UpdatedTick) 663 }) 664 665 // case 8 666 gtest.C(t, func(t *gtest.T) { 667 structG1 := StructG{ 668 Superior: "100", 669 UpdatedTick: 20, 670 } 671 structH1 := StructH{} 672 err := gconv.Scan(structG1, &structH1) 673 t.AssertNil(err) 674 t.Assert(*structH1.Superior, structG1.Superior) 675 t.Assert(*structH1.UpdatedTick, structG1.UpdatedTick) 676 t.Assert(structH1.StructG.Superior, structG1.Superior) 677 t.Assert(structH1.StructG.UpdatedTick, structG1.UpdatedTick) 678 }) 679 680 // case 9 681 gtest.C(t, func(t *gtest.T) { 682 structI := StructI{} 683 xxx := NullID("superior100") 684 structI.Master.Superior = &xxx 685 structI.Master.UpdatedTick = 30 686 structJ := StructJ{} 687 err := gconv.Scan(structI.Master, &structJ) 688 t.AssertNil(err) 689 t.Assert(*structJ.Superior, structI.Master.Superior) 690 t.Assert(*structJ.UpdatedTick, structI.Master.UpdatedTick) 691 t.Assert(structJ.StructA.Superior, structI.Master.Superior) 692 t.Assert(structJ.StructA.UpdatedTick, structI.Master.UpdatedTick) 693 }) 694 695 // case 10 696 gtest.C(t, func(t *gtest.T) { 697 structK := StructK{} 698 yyy := NullID("superior100") 699 structK.Master.Superior = &yyy 700 structK.Master.UpdatedTick = 40 701 structL := StructL{} 702 err := gconv.Scan(structK.Master, &structL) 703 t.AssertNil(err) 704 t.Assert(*structL.Superior, structK.Master.Superior) 705 t.Assert(*structL.UpdatedTick, structK.Master.UpdatedTick) 706 t.Assert(structL.StructA.Superior, structK.Master.Superior) 707 t.Assert(structL.StructA.UpdatedTick, structK.Master.UpdatedTick) 708 }) 709 }