github.com/wangyougui/gf/v2@v2.6.5/util/gconv/gconv_z_unit_map_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 "encoding/json" 11 "testing" 12 13 "gopkg.in/yaml.v3" 14 15 "github.com/wangyougui/gf/v2/frame/g" 16 "github.com/wangyougui/gf/v2/test/gtest" 17 "github.com/wangyougui/gf/v2/util/gconv" 18 "github.com/wangyougui/gf/v2/util/gutil" 19 ) 20 21 func Test_Map_Basic(t *testing.T) { 22 gtest.C(t, func(t *gtest.T) { 23 m1 := map[string]string{ 24 "k": "v", 25 } 26 m2 := map[int]string{ 27 3: "v", 28 } 29 m3 := map[float64]float32{ 30 1.22: 3.1, 31 } 32 t.Assert(gconv.Map(m1), g.Map{ 33 "k": "v", 34 }) 35 t.Assert(gconv.Map(m2), g.Map{ 36 "3": "v", 37 }) 38 t.Assert(gconv.Map(m3), g.Map{ 39 "1.22": "3.1", 40 }) 41 t.Assert(gconv.Map(`{"name":"goframe"}`), g.Map{ 42 "name": "goframe", 43 }) 44 t.Assert(gconv.Map(`{"name":"goframe"`), nil) 45 t.Assert(gconv.Map(`{goframe}`), nil) 46 t.Assert(gconv.Map([]byte(`{"name":"goframe"}`)), g.Map{ 47 "name": "goframe", 48 }) 49 t.Assert(gconv.Map([]byte(`{"name":"goframe"`)), nil) 50 t.Assert(gconv.Map([]byte(`{goframe}`)), nil) 51 }) 52 } 53 54 func Test_Map_Slice(t *testing.T) { 55 gtest.C(t, func(t *gtest.T) { 56 slice1 := g.Slice{"1", "2", "3", "4"} 57 slice2 := g.Slice{"1", "2", "3"} 58 slice3 := g.Slice{} 59 t.Assert(gconv.Map(slice1), g.Map{ 60 "1": "2", 61 "3": "4", 62 }) 63 t.Assert(gconv.Map(slice2), g.Map{ 64 "1": "2", 65 "3": nil, 66 }) 67 t.Assert(gconv.Map(slice3), g.Map{}) 68 }) 69 } 70 71 func Test_Maps_Basic(t *testing.T) { 72 params := g.Slice{ 73 g.Map{"id": 100, "name": "john"}, 74 g.Map{"id": 200, "name": "smith"}, 75 } 76 gtest.C(t, func(t *gtest.T) { 77 list := gconv.Maps(params) 78 t.Assert(len(list), 2) 79 t.Assert(list[0]["id"], 100) 80 t.Assert(list[1]["id"], 200) 81 }) 82 gtest.C(t, func(t *gtest.T) { 83 list := gconv.SliceMap(params) 84 t.Assert(len(list), 2) 85 t.Assert(list[0]["id"], 100) 86 t.Assert(list[1]["id"], 200) 87 }) 88 gtest.C(t, func(t *gtest.T) { 89 list := gconv.SliceMapDeep(params) 90 t.Assert(len(list), 2) 91 t.Assert(list[0]["id"], 100) 92 t.Assert(list[1]["id"], 200) 93 }) 94 gtest.C(t, func(t *gtest.T) { 95 type Base struct { 96 Age int 97 } 98 type User struct { 99 Id int 100 Name string 101 Base 102 } 103 104 users := make([]User, 0) 105 params := []g.Map{ 106 {"id": 1, "name": "john", "age": 18}, 107 {"id": 2, "name": "smith", "age": 20}, 108 } 109 err := gconv.SliceStruct(params, &users) 110 t.AssertNil(err) 111 t.Assert(len(users), 2) 112 t.Assert(users[0].Id, params[0]["id"]) 113 t.Assert(users[0].Name, params[0]["name"]) 114 t.Assert(users[0].Age, 18) 115 116 t.Assert(users[1].Id, params[1]["id"]) 117 t.Assert(users[1].Name, params[1]["name"]) 118 t.Assert(users[1].Age, 20) 119 }) 120 } 121 122 func Test_Maps_JsonStr(t *testing.T) { 123 jsonStr := `[{"id":100, "name":"john"},{"id":200, "name":"smith"}]` 124 gtest.C(t, func(t *gtest.T) { 125 list := gconv.Maps(jsonStr) 126 t.Assert(len(list), 2) 127 t.Assert(list[0]["id"], 100) 128 t.Assert(list[1]["id"], 200) 129 130 list = gconv.Maps([]byte(jsonStr)) 131 t.Assert(len(list), 2) 132 t.Assert(list[0]["id"], 100) 133 t.Assert(list[1]["id"], 200) 134 }) 135 136 gtest.C(t, func(t *gtest.T) { 137 t.Assert(gconv.Maps(`[id]`), nil) 138 t.Assert(gconv.Maps(`test`), nil) 139 t.Assert(gconv.Maps([]byte(`[id]`)), nil) 140 t.Assert(gconv.Maps([]byte(`test`)), nil) 141 }) 142 } 143 144 func Test_Map_StructWithGConvTag(t *testing.T) { 145 gtest.C(t, func(t *gtest.T) { 146 type User struct { 147 Uid int 148 Name string 149 SiteUrl string `gconv:"-"` 150 NickName string `gconv:"nickname, omitempty"` 151 Pass1 string `gconv:"password1"` 152 Pass2 string `gconv:"password2"` 153 } 154 user1 := User{ 155 Uid: 100, 156 Name: "john", 157 SiteUrl: "https://goframe.org", 158 Pass1: "123", 159 Pass2: "456", 160 } 161 user2 := &user1 162 map1 := gconv.Map(user1) 163 map2 := gconv.Map(user2) 164 t.Assert(map1["Uid"], 100) 165 t.Assert(map1["Name"], "john") 166 t.Assert(map1["SiteUrl"], nil) 167 t.Assert(map1["NickName"], nil) 168 t.Assert(map1["nickname"], nil) 169 t.Assert(map1["password1"], "123") 170 t.Assert(map1["password2"], "456") 171 172 t.Assert(map2["Uid"], 100) 173 t.Assert(map2["Name"], "john") 174 t.Assert(map2["SiteUrl"], nil) 175 t.Assert(map2["NickName"], nil) 176 t.Assert(map2["nickname"], nil) 177 t.Assert(map2["password1"], "123") 178 t.Assert(map2["password2"], "456") 179 }) 180 } 181 182 func Test_Map_StructWithJsonTag(t *testing.T) { 183 gtest.C(t, func(t *gtest.T) { 184 type User struct { 185 Uid int 186 Name string 187 SiteUrl string `json:"-"` 188 NickName string `json:"nickname, omitempty"` 189 Pass1 string `json:"password1"` 190 Pass2 string `json:"password2"` 191 } 192 user1 := User{ 193 Uid: 100, 194 Name: "john", 195 SiteUrl: "https://goframe.org", 196 Pass1: "123", 197 Pass2: "456", 198 } 199 user2 := &user1 200 map1 := gconv.Map(user1) 201 map2 := gconv.Map(user2) 202 t.Assert(map1["Uid"], 100) 203 t.Assert(map1["Name"], "john") 204 t.Assert(map1["SiteUrl"], nil) 205 t.Assert(map1["NickName"], nil) 206 t.Assert(map1["nickname"], nil) 207 t.Assert(map1["password1"], "123") 208 t.Assert(map1["password2"], "456") 209 210 t.Assert(map2["Uid"], 100) 211 t.Assert(map2["Name"], "john") 212 t.Assert(map2["SiteUrl"], nil) 213 t.Assert(map2["NickName"], nil) 214 t.Assert(map2["nickname"], nil) 215 t.Assert(map2["password1"], "123") 216 t.Assert(map2["password2"], "456") 217 }) 218 } 219 220 func Test_Map_StructWithCTag(t *testing.T) { 221 gtest.C(t, func(t *gtest.T) { 222 type User struct { 223 Uid int 224 Name string 225 SiteUrl string `c:"-"` 226 NickName string `c:"nickname, omitempty"` 227 Pass1 string `c:"password1"` 228 Pass2 string `c:"password2"` 229 } 230 user1 := User{ 231 Uid: 100, 232 Name: "john", 233 SiteUrl: "https://goframe.org", 234 Pass1: "123", 235 Pass2: "456", 236 } 237 user2 := &user1 238 map1 := gconv.Map(user1) 239 map2 := gconv.Map(user2) 240 t.Assert(map1["Uid"], 100) 241 t.Assert(map1["Name"], "john") 242 t.Assert(map1["SiteUrl"], nil) 243 t.Assert(map1["NickName"], nil) 244 t.Assert(map1["nickname"], nil) 245 t.Assert(map1["password1"], "123") 246 t.Assert(map1["password2"], "456") 247 248 t.Assert(map2["Uid"], 100) 249 t.Assert(map2["Name"], "john") 250 t.Assert(map2["SiteUrl"], nil) 251 t.Assert(map2["NickName"], nil) 252 t.Assert(map2["nickname"], nil) 253 t.Assert(map2["password1"], "123") 254 t.Assert(map2["password2"], "456") 255 }) 256 } 257 258 func Test_Map_PrivateAttribute(t *testing.T) { 259 type User struct { 260 Id int 261 name string 262 } 263 gtest.C(t, func(t *gtest.T) { 264 user := &User{1, "john"} 265 t.Assert(gconv.Map(user), g.Map{"Id": 1}) 266 }) 267 } 268 269 func Test_Map_Embedded(t *testing.T) { 270 type Base struct { 271 Id int 272 } 273 type User struct { 274 Base 275 Name string 276 } 277 type UserDetail struct { 278 User 279 Brief string 280 } 281 gtest.C(t, func(t *gtest.T) { 282 user := &User{} 283 user.Id = 1 284 user.Name = "john" 285 286 m := gconv.Map(user) 287 t.Assert(len(m), 2) 288 t.Assert(m["Id"], user.Id) 289 t.Assert(m["Name"], user.Name) 290 }) 291 gtest.C(t, func(t *gtest.T) { 292 user := &UserDetail{} 293 user.Id = 1 294 user.Name = "john" 295 user.Brief = "john guo" 296 297 m := gconv.Map(user) 298 t.Assert(len(m), 3) 299 t.Assert(m["Id"], user.Id) 300 t.Assert(m["Name"], user.Name) 301 t.Assert(m["Brief"], user.Brief) 302 }) 303 } 304 305 func Test_Map_Embedded2(t *testing.T) { 306 type Ids struct { 307 Id int `c:"id"` 308 Uid int `c:"uid"` 309 } 310 type Base struct { 311 Ids 312 CreateTime string `c:"create_time"` 313 } 314 type User struct { 315 Base 316 Passport string `c:"passport"` 317 Password string `c:"password"` 318 Nickname string `c:"nickname"` 319 } 320 gtest.C(t, func(t *gtest.T) { 321 user := new(User) 322 user.Id = 100 323 user.Nickname = "john" 324 user.CreateTime = "2019" 325 m := gconv.Map(user) 326 t.Assert(m["id"], "100") 327 t.Assert(m["nickname"], user.Nickname) 328 t.Assert(m["create_time"], "2019") 329 }) 330 gtest.C(t, func(t *gtest.T) { 331 user := new(User) 332 user.Id = 100 333 user.Nickname = "john" 334 user.CreateTime = "2019" 335 m := gconv.MapDeep(user) 336 t.Assert(m["id"], user.Id) 337 t.Assert(m["nickname"], user.Nickname) 338 t.Assert(m["create_time"], user.CreateTime) 339 }) 340 } 341 342 func Test_MapDeep2(t *testing.T) { 343 type A struct { 344 F string 345 G string 346 } 347 348 type B struct { 349 A 350 H string 351 } 352 353 type C struct { 354 A A 355 F string 356 } 357 358 type D struct { 359 I A 360 F string 361 } 362 363 gtest.C(t, func(t *gtest.T) { 364 b := new(B) 365 c := new(C) 366 d := new(D) 367 mb := gconv.MapDeep(b) 368 mc := gconv.MapDeep(c) 369 md := gconv.MapDeep(d) 370 t.Assert(gutil.MapContains(mb, "F"), true) 371 t.Assert(gutil.MapContains(mb, "G"), true) 372 t.Assert(gutil.MapContains(mb, "H"), true) 373 t.Assert(gutil.MapContains(mc, "A"), true) 374 t.Assert(gutil.MapContains(mc, "F"), true) 375 t.Assert(gutil.MapContains(mc, "G"), false) 376 t.Assert(gutil.MapContains(md, "F"), true) 377 t.Assert(gutil.MapContains(md, "I"), true) 378 t.Assert(gutil.MapContains(md, "H"), false) 379 t.Assert(gutil.MapContains(md, "G"), false) 380 }) 381 } 382 383 func Test_MapDeep3(t *testing.T) { 384 type Base struct { 385 Id int `c:"id"` 386 Date string `c:"date"` 387 } 388 type User struct { 389 UserBase Base `c:"base"` 390 Passport string `c:"passport"` 391 Password string `c:"password"` 392 Nickname string `c:"nickname"` 393 } 394 395 gtest.C(t, func(t *gtest.T) { 396 user := &User{ 397 UserBase: Base{ 398 Id: 1, 399 Date: "2019-10-01", 400 }, 401 Passport: "john", 402 Password: "123456", 403 Nickname: "JohnGuo", 404 } 405 m := gconv.MapDeep(user) 406 t.Assert(m, g.Map{ 407 "base": g.Map{ 408 "id": user.UserBase.Id, 409 "date": user.UserBase.Date, 410 }, 411 "passport": user.Passport, 412 "password": user.Password, 413 "nickname": user.Nickname, 414 }) 415 }) 416 417 gtest.C(t, func(t *gtest.T) { 418 user := &User{ 419 UserBase: Base{ 420 Id: 1, 421 Date: "2019-10-01", 422 }, 423 Passport: "john", 424 Password: "123456", 425 Nickname: "JohnGuo", 426 } 427 m := gconv.Map(user) 428 t.Assert(m, g.Map{ 429 "base": user.UserBase, 430 "passport": user.Passport, 431 "password": user.Password, 432 "nickname": user.Nickname, 433 }) 434 }) 435 } 436 437 func Test_MapDeepWithAttributeTag(t *testing.T) { 438 type Ids struct { 439 Id int `c:"id"` 440 Uid int `c:"uid"` 441 } 442 type Base struct { 443 Ids `json:"ids"` 444 CreateTime string `c:"create_time"` 445 } 446 type User struct { 447 Base `json:"base"` 448 Passport string `c:"passport"` 449 Password string `c:"password"` 450 Nickname string `c:"nickname"` 451 } 452 gtest.C(t, func(t *gtest.T) { 453 user := new(User) 454 user.Id = 100 455 user.Nickname = "john" 456 user.CreateTime = "2019" 457 m := gconv.Map(user) 458 t.Assert(m["id"], "") 459 t.Assert(m["nickname"], user.Nickname) 460 t.Assert(m["create_time"], "") 461 }) 462 gtest.C(t, func(t *gtest.T) { 463 user := new(User) 464 user.Id = 100 465 user.Nickname = "john" 466 user.CreateTime = "2019" 467 m := gconv.MapDeep(user) 468 t.Assert(m["base"].(map[string]interface{})["ids"].(map[string]interface{})["id"], user.Id) 469 t.Assert(m["nickname"], user.Nickname) 470 t.Assert(m["base"].(map[string]interface{})["create_time"], user.CreateTime) 471 }) 472 } 473 474 func Test_MapDeepWithNestedMapAnyAny(t *testing.T) { 475 type User struct { 476 ExtraAttributes g.Map `c:"extra_attributes"` 477 } 478 479 gtest.C(t, func(t *gtest.T) { 480 user := &User{ 481 ExtraAttributes: g.Map{ 482 "simple_attribute": 123, 483 "map_string_attribute": g.Map{ 484 "inner_value": 456, 485 }, 486 "map_interface_attribute": g.MapAnyAny{ 487 "inner_value": 456, 488 123: "integer_key_should_be_converted_to_string", 489 }, 490 }, 491 } 492 m := gconv.MapDeep(user) 493 t.Assert(m, g.Map{ 494 "extra_attributes": g.Map{ 495 "simple_attribute": 123, 496 "map_string_attribute": g.Map{ 497 "inner_value": user.ExtraAttributes["map_string_attribute"].(g.Map)["inner_value"], 498 }, 499 "map_interface_attribute": g.Map{ 500 "inner_value": user.ExtraAttributes["map_interface_attribute"].(g.MapAnyAny)["inner_value"], 501 "123": "integer_key_should_be_converted_to_string", 502 }, 503 }, 504 }) 505 }) 506 507 type Outer struct { 508 OuterStruct map[string]interface{} `c:"outer_struct" yaml:"outer_struct"` 509 Field3 map[string]interface{} `c:"field3" yaml:"field3"` 510 } 511 512 gtest.C(t, func(t *gtest.T) { 513 problemYaml := []byte(` 514 outer_struct: 515 field1: &anchor1 516 inner1: 123 517 inner2: 345 518 field2: 519 inner3: 456 520 inner4: 789 521 <<: *anchor1 522 field3: 523 123: integer_key 524 `) 525 parsed := &Outer{} 526 527 err := yaml.Unmarshal(problemYaml, parsed) 528 t.AssertNil(err) 529 530 _, err = json.Marshal(parsed) 531 t.AssertNil(err) 532 533 converted := gconv.MapDeep(parsed) 534 jsonData, err := json.Marshal(converted) 535 t.AssertNil(err) 536 537 t.Assert(string(jsonData), `{"field3":{"123":"integer_key"},"outer_struct":{"field1":{"inner1":123,"inner2":345},"field2":{"inner1":123,"inner2":345,"inner3":456,"inner4":789}}}`) 538 }) 539 } 540 541 func Test_MapWithDeepOption(t *testing.T) { 542 type Base struct { 543 Id int `c:"id"` 544 Date string `c:"date"` 545 } 546 type User struct { 547 UserBase Base `c:"base"` 548 Passport string `c:"passport"` 549 Password string `c:"password"` 550 Nickname string `c:"nickname"` 551 } 552 553 gtest.C(t, func(t *gtest.T) { 554 user := &User{ 555 UserBase: Base{ 556 Id: 1, 557 Date: "2019-10-01", 558 }, 559 Passport: "john", 560 Password: "123456", 561 Nickname: "JohnGuo", 562 } 563 m := gconv.Map(user) 564 t.Assert(m, g.Map{ 565 "base": user.UserBase, 566 "passport": user.Passport, 567 "password": user.Password, 568 "nickname": user.Nickname, 569 }) 570 }) 571 572 gtest.C(t, func(t *gtest.T) { 573 user := &User{ 574 UserBase: Base{ 575 Id: 1, 576 Date: "2019-10-01", 577 }, 578 Passport: "john", 579 Password: "123456", 580 Nickname: "JohnGuo", 581 } 582 m := gconv.Map(user, gconv.MapOption{Deep: true}) 583 t.Assert(m, g.Map{ 584 "base": g.Map{ 585 "id": user.UserBase.Id, 586 "date": user.UserBase.Date, 587 }, 588 "passport": user.Passport, 589 "password": user.Password, 590 "nickname": user.Nickname, 591 }) 592 }) 593 } 594 595 func TestMapStrStr(t *testing.T) { 596 gtest.C(t, func(t *gtest.T) { 597 t.Assert(gconv.MapStrStr(map[string]string{"k": "v"}), map[string]string{"k": "v"}) 598 t.Assert(gconv.MapStrStr(`{}`), nil) 599 }) 600 } 601 602 func TestMapStrStrDeep(t *testing.T) { 603 gtest.C(t, func(t *gtest.T) { 604 t.Assert(gconv.MapStrStrDeep(map[string]string{"k": "v"}), map[string]string{"k": "v"}) 605 t.Assert(gconv.MapStrStrDeep(`{"k":"v"}`), map[string]string{"k": "v"}) 606 t.Assert(gconv.MapStrStrDeep(`{}`), nil) 607 }) 608 } 609 610 func TestMapsDeep(t *testing.T) { 611 jsonStr := `[{"id":100, "name":"john"},{"id":200, "name":"smith"}]` 612 params := g.Slice{ 613 g.Map{"id": 100, "name": "john"}, 614 g.Map{"id": 200, "name": "smith"}, 615 } 616 617 gtest.C(t, func(t *gtest.T) { 618 t.Assert(gconv.MapsDeep(nil), nil) 619 }) 620 621 gtest.C(t, func(t *gtest.T) { 622 list := gconv.MapsDeep(params) 623 t.Assert(len(list), 2) 624 t.Assert(list[0]["id"], 100) 625 t.Assert(list[1]["id"], 200) 626 }) 627 628 gtest.C(t, func(t *gtest.T) { 629 list := gconv.MapsDeep(jsonStr) 630 t.Assert(len(list), 2) 631 t.Assert(list[0]["id"], 100) 632 t.Assert(list[1]["id"], 200) 633 634 list = gconv.MapsDeep([]byte(jsonStr)) 635 t.Assert(len(list), 2) 636 t.Assert(list[0]["id"], 100) 637 t.Assert(list[1]["id"], 200) 638 }) 639 640 gtest.C(t, func(t *gtest.T) { 641 t.Assert(gconv.MapsDeep(`[id]`), nil) 642 t.Assert(gconv.MapsDeep(`test`), nil) 643 t.Assert(gconv.MapsDeep([]byte(`[id]`)), nil) 644 t.Assert(gconv.MapsDeep([]byte(`test`)), nil) 645 t.Assert(gconv.MapsDeep([]string{}), nil) 646 }) 647 648 gtest.C(t, func(t *gtest.T) { 649 stringInterfaceMapList := make([]map[string]interface{}, 0) 650 stringInterfaceMapList = append(stringInterfaceMapList, map[string]interface{}{"id": 100}) 651 stringInterfaceMapList = append(stringInterfaceMapList, map[string]interface{}{"id": 200}) 652 list := gconv.MapsDeep(stringInterfaceMapList) 653 t.Assert(len(list), 2) 654 t.Assert(list[0]["id"], 100) 655 t.Assert(list[1]["id"], 200) 656 657 list = gconv.MapsDeep([]byte(jsonStr)) 658 t.Assert(len(list), 2) 659 t.Assert(list[0]["id"], 100) 660 t.Assert(list[1]["id"], 200) 661 }) 662 } 663 664 func TestMapWithJsonOmitEmpty(t *testing.T) { 665 gtest.C(t, func(t *gtest.T) { 666 type S struct { 667 Key string `json:",omitempty"` 668 Value interface{} `json:",omitempty"` 669 } 670 s := S{ 671 Key: "", 672 Value: 1, 673 } 674 m1 := gconv.Map(s) 675 t.Assert(m1, g.Map{ 676 "Key": "", 677 "Value": 1, 678 }) 679 680 m2 := gconv.Map(s, gconv.MapOption{ 681 Deep: false, 682 OmitEmpty: true, 683 Tags: nil, 684 }) 685 t.Assert(m2, g.Map{ 686 "Value": 1, 687 }) 688 }) 689 690 gtest.C(t, func(t *gtest.T) { 691 type ProductConfig struct { 692 Pid int `v:"required" json:"pid,omitempty"` 693 TimeSpan int `v:"required" json:"timeSpan,omitempty"` 694 } 695 type CreateGoodsDetail struct { 696 ProductConfig 697 AutoRenewFlag int `v:"required" json:"autoRenewFlag"` 698 } 699 s := &CreateGoodsDetail{ 700 ProductConfig: ProductConfig{ 701 Pid: 1, 702 TimeSpan: 0, 703 }, 704 AutoRenewFlag: 0, 705 } 706 m1 := gconv.Map(s) 707 t.Assert(m1, g.Map{ 708 "pid": 1, 709 "timeSpan": 0, 710 "autoRenewFlag": 0, 711 }) 712 713 m2 := gconv.Map(s, gconv.MapOption{ 714 Deep: false, 715 OmitEmpty: true, 716 Tags: nil, 717 }) 718 t.Assert(m2, g.Map{ 719 "pid": 1, 720 "autoRenewFlag": 0, 721 }) 722 }) 723 }