github.com/minio/simdjson-go@v0.4.6-0.20231116094823-04d21cddf993/parsed_json_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2020 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package simdjson 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 "io/ioutil" 24 "log" 25 "path/filepath" 26 "testing" 27 "time" 28 29 "github.com/klauspost/compress/zstd" 30 ) 31 32 const demo_json = `{"Image":{"Width":800,"Height":600,"Title":"View from 15th Floor","Thumbnail":{"Url":"http://www.example.com/image/481989943","Height":125,"Width":100},"Animated":false,"IDs":[116,943,234,38793]}}` 33 34 type tester interface { 35 Fatal(args ...interface{}) 36 } 37 38 func loadCompressed(t tester, file string) (ref []byte) { 39 dec, err := zstd.NewReader(nil) 40 if err != nil { 41 t.Fatal(err) 42 } 43 ref, err = ioutil.ReadFile(filepath.Join("testdata", file+".json.zst")) 44 if err != nil { 45 t.Fatal(err) 46 } 47 ref, err = dec.DecodeAll(ref, nil) 48 if err != nil { 49 t.Fatal(err) 50 } 51 52 return ref 53 } 54 55 var testCases = []struct { 56 name string 57 array bool 58 }{ 59 { 60 name: "apache_builds", 61 }, 62 { 63 name: "canada", 64 }, 65 { 66 name: "citm_catalog", 67 }, 68 { 69 name: "github_events", 70 array: true, 71 }, 72 { 73 name: "gsoc-2018", 74 }, 75 { 76 name: "instruments", 77 }, 78 { 79 name: "numbers", 80 array: true, 81 }, 82 { 83 name: "marine_ik", 84 }, 85 { 86 name: "mesh", 87 }, 88 { 89 name: "mesh.pretty", 90 }, 91 { 92 name: "twitterescaped", 93 }, 94 { 95 name: "twitter", 96 }, 97 { 98 name: "random", 99 }, 100 { 101 name: "update-center", 102 }, 103 } 104 105 func BenchmarkIter_MarshalJSONBuffer(b *testing.B) { 106 if !SupportedCPU() { 107 b.SkipNow() 108 } 109 for _, tt := range testCases { 110 b.Run(tt.name, func(b *testing.B) { 111 ref := loadCompressed(b, tt.name) 112 pj, err := Parse(ref, nil) 113 if err != nil { 114 b.Fatal(err) 115 } 116 iter := pj.Iter() 117 cpy := iter 118 output, err := cpy.MarshalJSON() 119 if err != nil { 120 b.Fatal(err) 121 } 122 b.SetBytes(int64(len(output))) 123 b.ReportAllocs() 124 b.ResetTimer() 125 for i := 0; i < b.N; i++ { 126 cpy := iter 127 output, err = cpy.MarshalJSONBuffer(output[:0]) 128 if err != nil { 129 b.Fatal(err) 130 } 131 } 132 }) 133 } 134 } 135 136 func BenchmarkGoMarshalJSON(b *testing.B) { 137 for _, tt := range testCases { 138 b.Run(tt.name, func(b *testing.B) { 139 ref := loadCompressed(b, tt.name) 140 var m interface{} 141 m = map[string]interface{}{} 142 if tt.array { 143 m = []interface{}{} 144 } 145 err := json.Unmarshal(ref, &m) 146 if err != nil { 147 b.Fatal(err) 148 } 149 output, err := json.Marshal(m) 150 if err != nil { 151 b.Fatal(err) 152 } 153 b.SetBytes(int64(len(output))) 154 b.ReportAllocs() 155 b.ResetTimer() 156 for i := 0; i < b.N; i++ { 157 output, err = json.Marshal(m) 158 if err != nil { 159 b.Fatal(err) 160 } 161 } 162 }) 163 } 164 } 165 166 func TestPrintJson(t *testing.T) { 167 if !SupportedCPU() { 168 t.SkipNow() 169 } 170 msg := []byte(demo_json) 171 expected := `{"Image":{"Width":800,"Height":600,"Title":"View from 15th Floor","Thumbnail":{"Url":"http://www.example.com/image/481989943","Height":125,"Width":100},"Animated":false,"IDs":[116,943,234,38793]}}` 172 173 pj, err := Parse(msg, nil) 174 175 if err != nil { 176 t.Errorf("parseMessage failed\n") 177 } 178 179 iter := pj.Iter() 180 out, err := iter.MarshalJSON() 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 if string(out) != expected { 186 t.Errorf("TestPrintJson: got: %s want: %s", out, expected) 187 } 188 } 189 190 func TestExchange(t *testing.T) { 191 if !SupportedCPU() { 192 t.SkipNow() 193 } 194 input := `{"value": -20}` 195 pj, err := Parse([]byte(input), nil) 196 if err != nil { 197 t.Errorf("Parse failed: %v", err) 198 return 199 } 200 for i := 0; i < 200; i++ { 201 i := i 202 t.Run(fmt.Sprint(i), func(t *testing.T) { 203 t.Parallel() 204 var cl *ParsedJson 205 var o *Object 206 for j := 0; j < 10; j++ { 207 cl = pj.Clone(cl) 208 iter := cl.Iter() 209 iter.Advance() 210 _, r, err := iter.Root(&iter) 211 if err != nil { 212 t.Fatalf("Root failed: %v", err) 213 } 214 o, err = r.Object(o) 215 if err != nil { 216 t.Fatalf("Object failed: %v", err) 217 } 218 _, _, err = o.NextElementBytes(r) 219 if err != nil { 220 t.Fatalf("NextElementBytes failed: %v", err) 221 } 222 want := uint64(i + j*100) 223 err = r.SetUInt(want) 224 if err != nil { 225 t.Fatalf("SetUInt failed: %v", err) 226 return 227 } 228 time.Sleep(10 * time.Millisecond) 229 v, err := r.Uint() 230 if err != nil { 231 t.Fatalf("Uint failed: %v", err) 232 return 233 } 234 if v != want { 235 t.Errorf("want %d, got %d", want, v) 236 } 237 } 238 }) 239 } 240 } 241 242 func TestIter_SetNull(t *testing.T) { 243 if !SupportedCPU() { 244 t.SkipNow() 245 } 246 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 247 tests := []struct { 248 want string 249 }{ 250 { 251 want: `{"0val":{"true":null,"false":null,"nullval":null},"1val":{"float":null,"int":null,"uint":null},"stringval":null,"array":[null,null,null,null,null,null,null]}`, 252 }, 253 } 254 255 for _, test := range tests { 256 t.Run("null", func(t *testing.T) { 257 pj, err := Parse([]byte(input), nil) 258 if err != nil { 259 t.Errorf("parseMessage failed\n") 260 return 261 } 262 root := pj.Iter() 263 // Queue root 264 root.AdvanceInto() 265 if err != nil { 266 t.Errorf("root failed: %v", err) 267 return 268 } 269 iter := root 270 for { 271 typ := iter.Type() 272 switch typ { 273 case TypeBool, TypeNull: 274 //t.Logf("setting to %v", test.setTo) 275 err := iter.SetNull() 276 if err != nil { 277 t.Errorf("Unable to set value: %v", err) 278 } 279 280 if iter.Type() != TypeNull { 281 t.Errorf("Want type %v, got %v", TypeNull, iter.Type()) 282 } 283 case TypeFloat, TypeUint, TypeInt: 284 err := iter.SetNull() 285 if err != nil { 286 t.Errorf("Unable to set value: %v", err) 287 } 288 289 if iter.Type() != TypeNull { 290 t.Errorf("Want type %v, got %v", TypeNull, iter.Type()) 291 } 292 case TypeString: 293 // Most are keys so cannot be nulled. 294 s, _ := iter.String() 295 switch s { 296 case "astring", "initial value": 297 err := iter.SetNull() 298 if err != nil { 299 t.Errorf("Unable to set value: %v", err) 300 } 301 302 if iter.Type() != TypeNull { 303 t.Errorf("Want type %v, got %v", TypeNull, iter.Type()) 304 } 305 } 306 case TypeRoot, TypeObject, TypeArray: 307 default: 308 err := iter.SetNull() 309 if err == nil { 310 t.Errorf("Value should not be settable for type %v", typ) 311 } 312 } 313 if iter.PeekNextTag() == TagEnd { 314 break 315 } 316 iter.AdvanceInto() 317 } 318 out, err := root.MarshalJSON() 319 if err != nil { 320 t.Fatal(err) 321 } 322 if string(out) != test.want { 323 t.Errorf("want: %s\n got: %s", test.want, string(out)) 324 } 325 ser := NewSerializer() 326 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 327 if err != nil { 328 t.Fatal(err) 329 } 330 iter2 := pj2.Iter() 331 out2, err := iter2.MarshalJSON() 332 if err != nil { 333 t.Fatal(err) 334 } 335 if !bytes.Equal(out, out2) { 336 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 337 } 338 }) 339 } 340 } 341 342 func TestIter_SetNull_ObjArr(t *testing.T) { 343 if !SupportedCPU() { 344 t.SkipNow() 345 } 346 347 tests := []struct { 348 input string 349 skipN int 350 want string 351 nullRoot bool 352 }{ 353 { 354 input: `{"0val":{"true":true}}`, 355 skipN: 1, 356 want: `{"0val":null}`, 357 }, 358 { 359 input: `{"0val":[1,2,334,5,454,6,5,true,5,6,78]}`, 360 skipN: 1, 361 want: `{"0val":null}`, 362 }, 363 { 364 input: `[{"0val":[1,2,334,5,454,6,5,true,5,6,78]}, {"2val":{"true":true}}]`, 365 skipN: 1, 366 want: `[null,null]`, 367 }, 368 { 369 input: `[{"0val":[1,2,334,5,454,6,5,true,5,6,78]}, {"2val":{"true":true}}]`, 370 nullRoot: true, 371 want: `null`, 372 }, 373 } 374 375 for i, test := range tests { 376 t.Run(fmt.Sprint(i), func(t *testing.T) { 377 skip := test.skipN 378 pj, err := ParseND([]byte(test.input), nil) 379 if err != nil { 380 t.Errorf("parseMessage failed\n") 381 return 382 } 383 root := pj.Iter() 384 // Queue root 385 root.AdvanceInto() 386 if err != nil { 387 t.Errorf("root failed: %v", err) 388 return 389 } 390 iter := root 391 for { 392 typ := iter.Type() 393 switch typ { 394 case TypeObject, TypeArray: 395 if skip > 0 { 396 skip-- 397 break 398 } 399 //t.Logf("setting to %v", test.setTo) 400 err := iter.SetNull() 401 if err != nil { 402 t.Errorf("Unable to set value: %v", err) 403 } 404 405 if iter.Type() != TypeNull { 406 t.Errorf("Want type %v, got %v", TypeNull, iter.Type()) 407 } 408 case TypeRoot: 409 if test.nullRoot { 410 err := iter.SetNull() 411 if err != nil { 412 t.Errorf("Unable to set value: %v", err) 413 } 414 415 if iter.Type() != TypeNull { 416 t.Errorf("Want type %v, got %v", TypeNull, iter.Type()) 417 } 418 } 419 default: 420 } 421 if iter.PeekNextTag() == TagEnd { 422 break 423 } 424 iter.AdvanceInto() 425 } 426 root = pj.Iter() 427 out, err := root.MarshalJSON() 428 if err != nil { 429 t.Fatal(err) 430 } 431 if string(out) != test.want { 432 t.Errorf("want: %s\n got: %s", test.want, string(out)) 433 } 434 ser := NewSerializer() 435 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 436 if err != nil { 437 t.Fatal(err) 438 } 439 iter2 := pj2.Iter() 440 out2, err := iter2.MarshalJSON() 441 if err != nil { 442 t.Fatal(err) 443 } 444 if !bytes.Equal(out, out2) { 445 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 446 } 447 }) 448 } 449 } 450 451 func TestObject_DeleteElems(t *testing.T) { 452 if !SupportedCPU() { 453 t.SkipNow() 454 } 455 input := `{"one": 1, "two": 2.02, "three": "33333", "four": 0, "five": false, "six": true, "seven": {"key": "value"}, "eight": [1,2,2,3]}` 456 tests := []struct { 457 want string 458 fn func(key string) bool 459 }{ 460 { 461 want: `{}`, 462 fn: func(key string) bool { 463 return true 464 }, 465 }, 466 { 467 want: `{"two":2.02,"three":"33333","four":0,"five":false,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 468 fn: func(key string) bool { 469 return key == "one" 470 }, 471 }, 472 { 473 want: `{"one":1,"three":"33333","four":0,"five":false,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 474 fn: func(key string) bool { 475 return key == "two" 476 }, 477 }, 478 { 479 want: `{"one":1,"two":2.02,"four":0,"five":false,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 480 fn: func(key string) bool { 481 return key == "three" 482 }, 483 }, 484 { 485 want: `{"one":1,"two":2.02,"three":"33333","five":false,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 486 fn: func(key string) bool { 487 return key == "four" 488 }, 489 }, 490 { 491 want: `{"one":1,"two":2.02,"three":"33333","four":0,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 492 fn: func(key string) bool { 493 return key == "five" 494 }, 495 }, 496 { 497 want: `{"one":1,"two":2.02,"three":"33333","four":0,"five":false,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 498 fn: func(key string) bool { 499 return key == "six" 500 }, 501 }, 502 { 503 want: `{"one":1,"two":2.02,"three":"33333","four":0,"five":false,"six":true,"eight":[1,2,2,3]}`, 504 fn: func(key string) bool { 505 return key == "seven" 506 }, 507 }, 508 { 509 want: `{"one":1,"two":2.02,"three":"33333","four":0,"five":false,"six":true,"seven":{"key":"value"}}`, 510 fn: func(key string) bool { 511 return key == "eight" 512 }, 513 }, 514 { 515 want: `{"one":1,"two":2.02,"three":"33333","four":0,"five":false,"six":true,"seven":{"key":"value"},"eight":[1,2,2,3]}`, 516 fn: func(key string) bool { 517 return false 518 }, 519 }, 520 } 521 522 for i, test := range tests { 523 t.Run(fmt.Sprint(i), func(t *testing.T) { 524 pj, err := Parse([]byte(input), nil) 525 if err != nil { 526 t.Errorf("parseMessage failed\n") 527 return 528 } 529 530 // Queue root 531 iter := pj.Iter() 532 iter.AdvanceInto() 533 534 _, root, err := iter.Root(nil) 535 if err != nil { 536 t.Fatalf("root failed: %v", err) 537 return 538 } 539 obj, err := root.Object(nil) 540 if err != nil { 541 t.Fatalf("obj failed: %v", err) 542 return 543 } 544 545 err = obj.DeleteElems(func(key []byte, i Iter) bool { 546 return test.fn(string(key)) 547 }, nil) 548 if err != nil { 549 t.Fatal(err) 550 } 551 552 // Test we don't delete more than we should 553 err = obj.DeleteElems(nil, map[string]struct{}{"unwanted": {}}) 554 if err != nil { 555 t.Fatal(err) 556 } 557 out, err := root.MarshalJSON() 558 if err != nil { 559 t.Fatal(err) 560 } 561 if string(out) != test.want { 562 t.Errorf("want: %s\n got: %s", test.want, string(out)) 563 } 564 ser := NewSerializer() 565 b := ser.Serialize(nil, *pj) 566 if err != nil { 567 t.Fatal(err) 568 } 569 pj2, err := ser.Deserialize(b, nil) 570 if err != nil { 571 t.Fatal(err) 572 } 573 iter = pj2.Iter() 574 iter.AdvanceInto() 575 576 _, root, err = iter.Root(nil) 577 if err != nil { 578 t.Fatalf("root failed: %v", err) 579 return 580 } 581 out, err = root.MarshalJSON() 582 if err != nil { 583 t.Fatal(err) 584 } 585 if string(out) != test.want { 586 t.Errorf("want: %s\n got: %s", test.want, string(out)) 587 } 588 }) 589 } 590 } 591 592 func TestArray_DeleteElements(t *testing.T) { 593 if !SupportedCPU() { 594 t.SkipNow() 595 } 596 input := `[1, 2.02, "33333", false, true, {"key": "value"}, [1,2,2,3], null, -42]` 597 tests := []struct { 598 want string 599 del int 600 }{ 601 { 602 want: `[]`, 603 del: -1, 604 }, 605 { 606 want: `[1,2.02,"33333",false,true,{"key":"value"},[1,2,2,3],null,-42]`, 607 del: 100, 608 }, 609 { 610 want: `[2.02,"33333",false,true,{"key":"value"},[1,2,2,3],null,-42]`, 611 del: 0, 612 }, 613 { 614 want: `[1,"33333",false,true,{"key":"value"},[1,2,2,3],null,-42]`, 615 del: 1, 616 }, { 617 want: `[1,2.02,false,true,{"key":"value"},[1,2,2,3],null,-42]`, 618 del: 2, 619 }, { 620 want: `[1,2.02,"33333",true,{"key":"value"},[1,2,2,3],null,-42]`, 621 del: 3, 622 }, { 623 want: `[1,2.02,"33333",false,{"key":"value"},[1,2,2,3],null,-42]`, 624 del: 4, 625 }, { 626 want: `[1,2.02,"33333",false,true,[1,2,2,3],null,-42]`, 627 del: 5, 628 }, { 629 want: `[1,2.02,"33333",false,true,{"key":"value"},null,-42]`, 630 del: 6, 631 }, { 632 want: `[1,2.02,"33333",false,true,{"key":"value"},[1,2,2,3],-42]`, 633 del: 7, 634 }, { 635 want: `[1,2.02,"33333",false,true,{"key":"value"},[1,2,2,3],null]`, 636 del: 8, 637 }, 638 } 639 640 for i, test := range tests { 641 t.Run(fmt.Sprint(i), func(t *testing.T) { 642 pj, err := Parse([]byte(input), nil) 643 if err != nil { 644 t.Errorf("parseMessage failed\n") 645 return 646 } 647 648 // Queue root 649 iter := pj.Iter() 650 iter.AdvanceInto() 651 652 _, root, err := iter.Root(nil) 653 if err != nil { 654 t.Fatalf("root failed: %v", err) 655 return 656 } 657 arr, err := root.Array(nil) 658 if err != nil { 659 t.Fatalf("obj failed: %v", err) 660 return 661 } 662 var idx int 663 arr.DeleteElems(func(i Iter) bool { 664 del := test.del < 0 || idx == test.del 665 idx++ 666 return del 667 }) 668 669 out, err := root.MarshalJSON() 670 if err != nil { 671 t.Fatal(err) 672 } 673 if string(out) != test.want { 674 t.Errorf("want: %s\n got: %s", test.want, string(out)) 675 } 676 ser := NewSerializer() 677 b := ser.Serialize(nil, *pj) 678 if err != nil { 679 t.Fatal(err) 680 } 681 pj2, err := ser.Deserialize(b, nil) 682 if err != nil { 683 t.Fatal(err) 684 } 685 iter = pj2.Iter() 686 iter.AdvanceInto() 687 688 _, root, err = iter.Root(nil) 689 if err != nil { 690 t.Fatalf("root failed: %v", err) 691 return 692 } 693 out, err = root.MarshalJSON() 694 if err != nil { 695 t.Fatal(err) 696 } 697 if string(out) != test.want { 698 t.Errorf("want: %s\n got: %s", test.want, string(out)) 699 } 700 }) 701 } 702 } 703 704 func TestIter_SetBool(t *testing.T) { 705 if !SupportedCPU() { 706 t.SkipNow() 707 } 708 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 709 tests := []struct { 710 setTo bool 711 want string 712 }{ 713 { 714 setTo: true, 715 want: `{"0val":{"true":true,"false":true,"nullval":true},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[true,true,true,"astring",-42,9223372036854775808,1.23455]}`, 716 }, 717 { 718 setTo: false, 719 want: `{"0val":{"true":false,"false":false,"nullval":false},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[false,false,false,"astring",-42,9223372036854775808,1.23455]}`, 720 }, 721 } 722 723 for _, test := range tests { 724 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 725 pj, err := Parse([]byte(input), nil) 726 if err != nil { 727 t.Errorf("parseMessage failed\n") 728 return 729 } 730 root := pj.Iter() 731 // Queue root 732 root.AdvanceInto() 733 if err != nil { 734 t.Errorf("root failed: %v", err) 735 return 736 } 737 iter := root 738 for { 739 typ := iter.Type() 740 switch typ { 741 case TypeBool, TypeNull: 742 //t.Logf("setting to %v", test.setTo) 743 err := iter.SetBool(test.setTo) 744 if err != nil { 745 t.Errorf("Unable to set value: %v", err) 746 } 747 val, err := iter.Bool() 748 if err != nil { 749 t.Errorf("Unable to retrieve value: %v", err) 750 } 751 752 if val != test.setTo { 753 t.Errorf("Want value %v, got %v", test.setTo, val) 754 } 755 default: 756 err := iter.SetBool(test.setTo) 757 if err == nil { 758 t.Errorf("Value should not be settable for type %v", typ) 759 } 760 } 761 if iter.PeekNextTag() == TagEnd { 762 break 763 } 764 iter.AdvanceInto() 765 } 766 out, err := root.MarshalJSON() 767 if err != nil { 768 t.Fatal(err) 769 } 770 if string(out) != test.want { 771 t.Errorf("want: %s\n got: %s", test.want, string(out)) 772 } 773 ser := NewSerializer() 774 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 775 if err != nil { 776 t.Fatal(err) 777 } 778 iter2 := pj2.Iter() 779 out2, err := iter2.MarshalJSON() 780 if err != nil { 781 t.Fatal(err) 782 } 783 if !bytes.Equal(out, out2) { 784 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 785 } 786 }) 787 } 788 } 789 790 func TestIter_SetFloat(t *testing.T) { 791 if !SupportedCPU() { 792 t.SkipNow() 793 } 794 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 795 tests := []struct { 796 setTo float64 797 want string 798 }{ 799 { 800 setTo: 69.420, 801 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":69.42,"int":69.42,"uint":69.42},"stringval":"initial value","array":[null,true,false,"astring",69.42,69.42,69.42]}`, 802 }, 803 { 804 setTo: 10e30, 805 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":1e+31,"int":1e+31,"uint":1e+31},"stringval":"initial value","array":[null,true,false,"astring",1e+31,1e+31,1e+31]}`, 806 }, 807 } 808 809 for _, test := range tests { 810 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 811 pj, err := Parse([]byte(input), nil) 812 if err != nil { 813 t.Errorf("parseMessage failed\n") 814 return 815 } 816 root := pj.Iter() 817 // Queue root 818 root.AdvanceInto() 819 if err != nil { 820 t.Errorf("root failed: %v", err) 821 return 822 } 823 iter := root 824 for { 825 typ := iter.Type() 826 switch typ { 827 case TypeInt, TypeFloat, TypeUint: 828 //t.Logf("setting to %v", test.setTo) 829 err := iter.SetFloat(test.setTo) 830 if err != nil { 831 t.Errorf("Unable to set value: %v", err) 832 } 833 val, err := iter.Float() 834 if err != nil { 835 t.Errorf("Unable to retrieve value: %v", err) 836 } 837 838 if val != test.setTo { 839 t.Errorf("Want value %v, got %v", test.setTo, val) 840 } 841 case TypeString: 842 // Do not replace strings... 843 default: 844 err := iter.SetFloat(test.setTo) 845 if err == nil { 846 t.Errorf("Value should not be settable for type %v", typ) 847 } 848 } 849 if iter.PeekNextTag() == TagEnd { 850 break 851 } 852 iter.AdvanceInto() 853 } 854 out, err := root.MarshalJSON() 855 if err != nil { 856 t.Fatal(err) 857 } 858 if string(out) != test.want { 859 t.Errorf("want: %s\n got: %s", test.want, string(out)) 860 } 861 ser := NewSerializer() 862 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 863 if err != nil { 864 t.Fatal(err) 865 } 866 iter2 := pj2.Iter() 867 out2, err := iter2.MarshalJSON() 868 if err != nil { 869 t.Fatal(err) 870 } 871 if !bytes.Equal(out, out2) { 872 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 873 } 874 }) 875 } 876 } 877 878 func TestIter_SetInt(t *testing.T) { 879 if !SupportedCPU() { 880 t.SkipNow() 881 } 882 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 883 tests := []struct { 884 setTo int64 885 want string 886 }{ 887 { 888 setTo: -69, 889 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":-69,"int":-69,"uint":-69},"stringval":"initial value","array":[null,true,false,"astring",-69,-69,-69]}`, 890 }, 891 { 892 setTo: 42, 893 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":42,"int":42,"uint":42},"stringval":"initial value","array":[null,true,false,"astring",42,42,42]}`, 894 }, 895 } 896 897 for _, test := range tests { 898 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 899 pj, err := Parse([]byte(input), nil) 900 if err != nil { 901 t.Errorf("parseMessage failed\n") 902 return 903 } 904 root := pj.Iter() 905 // Queue root 906 root.AdvanceInto() 907 if err != nil { 908 t.Errorf("root failed: %v", err) 909 return 910 } 911 iter := root 912 for { 913 typ := iter.Type() 914 switch typ { 915 case TypeInt, TypeFloat, TypeUint: 916 //t.Logf("setting to %v", test.setTo) 917 err := iter.SetInt(test.setTo) 918 if err != nil { 919 t.Errorf("Unable to set value: %v", err) 920 } 921 val, err := iter.Int() 922 if err != nil { 923 t.Errorf("Unable to retrieve value: %v", err) 924 } 925 926 if val != test.setTo { 927 t.Errorf("Want value %v, got %v", test.setTo, val) 928 } 929 case TypeString: 930 // Do not replace strings... 931 932 default: 933 err := iter.SetInt(test.setTo) 934 if err == nil { 935 t.Errorf("Value should not be settable for type %v", typ) 936 } 937 } 938 if iter.PeekNextTag() == TagEnd { 939 break 940 } 941 iter.AdvanceInto() 942 } 943 out, err := root.MarshalJSON() 944 if err != nil { 945 t.Fatal(err) 946 } 947 if string(out) != test.want { 948 t.Errorf("want: %s\n got: %s", test.want, string(out)) 949 } 950 ser := NewSerializer() 951 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 952 if err != nil { 953 t.Fatal(err) 954 } 955 iter2 := pj2.Iter() 956 out2, err := iter2.MarshalJSON() 957 if err != nil { 958 t.Fatal(err) 959 } 960 if !bytes.Equal(out, out2) { 961 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 962 } 963 }) 964 } 965 } 966 967 func TestIter_SetUInt(t *testing.T) { 968 if !SupportedCPU() { 969 t.SkipNow() 970 } 971 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 972 tests := []struct { 973 setTo uint64 974 want string 975 }{ 976 { 977 setTo: 69, 978 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":69,"int":69,"uint":69},"stringval":"initial value","array":[null,true,false,"astring",69,69,69]}`, 979 }, 980 { 981 setTo: 420, 982 want: `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":420,"int":420,"uint":420},"stringval":"initial value","array":[null,true,false,"astring",420,420,420]}`, 983 }, 984 } 985 986 for _, test := range tests { 987 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 988 pj, err := Parse([]byte(input), nil) 989 if err != nil { 990 t.Errorf("parseMessage failed\n") 991 return 992 } 993 root := pj.Iter() 994 // Queue root 995 root.AdvanceInto() 996 if err != nil { 997 t.Errorf("root failed: %v", err) 998 return 999 } 1000 iter := root 1001 for { 1002 typ := iter.Type() 1003 switch typ { 1004 case TypeInt, TypeFloat, TypeUint: 1005 //t.Logf("setting to %v", test.setTo) 1006 err := iter.SetUInt(test.setTo) 1007 if err != nil { 1008 t.Errorf("Unable to set value: %v", err) 1009 } 1010 val, err := iter.Uint() 1011 if err != nil { 1012 t.Errorf("Unable to retrieve value: %v", err) 1013 } 1014 1015 if val != test.setTo { 1016 t.Errorf("Want value %v, got %v", test.setTo, val) 1017 } 1018 case TypeString: 1019 // Do not replace strings... 1020 default: 1021 err := iter.SetUInt(test.setTo) 1022 if err == nil { 1023 t.Errorf("Value should not be settable for type %v", typ) 1024 } 1025 } 1026 if iter.PeekNextTag() == TagEnd { 1027 break 1028 } 1029 iter.AdvanceInto() 1030 } 1031 out, err := root.MarshalJSON() 1032 if err != nil { 1033 t.Fatal(err) 1034 } 1035 if string(out) != test.want { 1036 t.Errorf("want: %s\n got: %s", test.want, string(out)) 1037 } 1038 ser := NewSerializer() 1039 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 1040 if err != nil { 1041 t.Fatal(err) 1042 } 1043 iter2 := pj2.Iter() 1044 out2, err := iter2.MarshalJSON() 1045 if err != nil { 1046 t.Fatal(err) 1047 } 1048 if !bytes.Equal(out, out2) { 1049 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 1050 } 1051 }) 1052 } 1053 } 1054 1055 func TestIter_SetString(t *testing.T) { 1056 if !SupportedCPU() { 1057 t.SkipNow() 1058 } 1059 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 1060 tests := []struct { 1061 setTo string 1062 want string 1063 }{ 1064 { 1065 setTo: "anotherval", 1066 want: `{"anotherval":{"anotherval":true,"anotherval":false,"anotherval":null},"anotherval":{"anotherval":"anotherval","anotherval":"anotherval","anotherval":"anotherval"},"anotherval":"anotherval","anotherval":[null,true,false,"anotherval","anotherval","anotherval","anotherval"]}`, 1067 }, 1068 { 1069 setTo: "", 1070 want: `{"":{"":true,"":false,"":null},"":{"":"","":"","":""},"":"","":[null,true,false,"","","",""]}`, 1071 }, 1072 { 1073 setTo: "\t", 1074 want: `{"\t":{"\t":true,"\t":false,"\t":null},"\t":{"\t":"\t","\t":"\t","\t":"\t"},"\t":"\t","\t":[null,true,false,"\t","\t","\t","\t"]}`, 1075 }, 1076 } 1077 1078 for _, test := range tests { 1079 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 1080 pj, err := Parse([]byte(input), nil) 1081 if err != nil { 1082 t.Errorf("parseMessage failed\n") 1083 return 1084 } 1085 root := pj.Iter() 1086 // Queue root 1087 root.AdvanceInto() 1088 if err != nil { 1089 t.Errorf("root failed: %v", err) 1090 return 1091 } 1092 iter := root 1093 for { 1094 typ := iter.Type() 1095 switch typ { 1096 case TypeString, TypeInt, TypeFloat, TypeUint: 1097 //t.Logf("setting to %v", test.setTo) 1098 err := iter.SetString(test.setTo) 1099 if err != nil { 1100 t.Errorf("Unable to set value: %v", err) 1101 } 1102 val, err := iter.String() 1103 if err != nil { 1104 t.Errorf("Unable to retrieve value: %v", err) 1105 } 1106 1107 if val != test.setTo { 1108 t.Errorf("Want value %v, got %v", test.setTo, val) 1109 } 1110 default: 1111 err := iter.SetString(test.setTo) 1112 if err == nil { 1113 t.Errorf("Value should not be settable for type %v", typ) 1114 } 1115 } 1116 if iter.PeekNextTag() == TagEnd { 1117 break 1118 } 1119 iter.AdvanceInto() 1120 } 1121 out, err := root.MarshalJSON() 1122 if err != nil { 1123 t.Fatal(err) 1124 } 1125 if string(out) != test.want { 1126 t.Errorf("want: %s\n got: %s", test.want, string(out)) 1127 } 1128 ser := NewSerializer() 1129 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 1130 if err != nil { 1131 t.Fatal(err) 1132 } 1133 iter2 := pj2.Iter() 1134 out2, err := iter2.MarshalJSON() 1135 if err != nil { 1136 t.Fatal(err) 1137 } 1138 if !bytes.Equal(out, out2) { 1139 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 1140 } 1141 }) 1142 } 1143 } 1144 1145 func TestIter_SetStringBytes(t *testing.T) { 1146 if !SupportedCPU() { 1147 t.SkipNow() 1148 } 1149 input := `{"0val":{"true":true,"false":false,"nullval":null},"1val":{"float":12.3456,"int":-42,"uint":9223372036854775808},"stringval":"initial value","array":[null,true,false,"astring",-42,9223372036854775808,1.23455]}` 1150 tests := []struct { 1151 setTo []byte 1152 want string 1153 }{ 1154 { 1155 setTo: []byte("anotherval"), 1156 want: `{"anotherval":{"anotherval":true,"anotherval":false,"anotherval":null},"anotherval":{"anotherval":"anotherval","anotherval":"anotherval","anotherval":"anotherval"},"anotherval":"anotherval","anotherval":[null,true,false,"anotherval","anotherval","anotherval","anotherval"]}`, 1157 }, 1158 { 1159 setTo: []byte{}, 1160 want: `{"":{"":true,"":false,"":null},"":{"":"","":"","":""},"":"","":[null,true,false,"","","",""]}`, 1161 }, 1162 { 1163 setTo: []byte(nil), 1164 want: `{"":{"":true,"":false,"":null},"":{"":"","":"","":""},"":"","":[null,true,false,"","","",""]}`, 1165 }, 1166 } 1167 1168 for _, test := range tests { 1169 t.Run(fmt.Sprint(test.setTo), func(t *testing.T) { 1170 pj, err := Parse([]byte(input), nil) 1171 if err != nil { 1172 t.Errorf("parseMessage failed\n") 1173 return 1174 } 1175 root := pj.Iter() 1176 // Queue root 1177 root.AdvanceInto() 1178 if err != nil { 1179 t.Errorf("root failed: %v", err) 1180 return 1181 } 1182 iter := root 1183 for { 1184 typ := iter.Type() 1185 switch typ { 1186 case TypeString, TypeInt, TypeFloat, TypeUint: 1187 //t.Logf("setting to %v", test.setTo) 1188 err := iter.SetStringBytes(test.setTo) 1189 if err != nil { 1190 t.Errorf("Unable to set value: %v", err) 1191 } 1192 val, err := iter.StringBytes() 1193 if err != nil { 1194 t.Errorf("Unable to retrieve value: %v", err) 1195 } 1196 1197 if !bytes.Equal(val, test.setTo) { 1198 t.Errorf("Want value %v, got %v", test.setTo, val) 1199 } 1200 default: 1201 err := iter.SetStringBytes(test.setTo) 1202 if err == nil { 1203 t.Errorf("Value should not be settable for type %v", typ) 1204 } 1205 } 1206 if iter.PeekNextTag() == TagEnd { 1207 break 1208 } 1209 iter.AdvanceInto() 1210 } 1211 out, err := root.MarshalJSON() 1212 if err != nil { 1213 t.Fatal(err) 1214 } 1215 if string(out) != test.want { 1216 t.Errorf("want: %s\n got: %s", test.want, string(out)) 1217 } 1218 ser := NewSerializer() 1219 pj2, err := ser.Deserialize(ser.Serialize(nil, *pj), nil) 1220 if err != nil { 1221 t.Fatal(err) 1222 } 1223 iter2 := pj2.Iter() 1224 out2, err := iter2.MarshalJSON() 1225 if err != nil { 1226 t.Fatal(err) 1227 } 1228 if !bytes.Equal(out, out2) { 1229 t.Errorf("roundtrip mismatch: %s != %s", out, out2) 1230 } 1231 }) 1232 } 1233 } 1234 1235 func ExampleIter_FindElement() { 1236 if !SupportedCPU() { 1237 // Fake it 1238 fmt.Println("int\n100 <nil>") 1239 return 1240 } 1241 input := `{ 1242 "Image": 1243 { 1244 "Animated": false, 1245 "Height": 600, 1246 "IDs": 1247 [ 1248 116, 1249 943, 1250 234, 1251 38793 1252 ], 1253 "Thumbnail": 1254 { 1255 "Height": 125, 1256 "Url": "http://www.example.com/image/481989943", 1257 "Width": 100 1258 }, 1259 "Title": "View from 15th Floor", 1260 "Width": 800 1261 }, 1262 "Alt": "Image of city" 1263 }` 1264 pj, err := Parse([]byte(input), nil) 1265 if err != nil { 1266 log.Fatal(err) 1267 } 1268 i := pj.Iter() 1269 1270 // Find element in path. 1271 elem, err := i.FindElement(nil, "Image", "Thumbnail", "Width") 1272 if err != nil { 1273 log.Fatal(err) 1274 } 1275 1276 // Print result: 1277 fmt.Println(elem.Type) 1278 fmt.Println(elem.Iter.StringCvt()) 1279 1280 // Output: 1281 // int 1282 // 100 <nil> 1283 } 1284 1285 func ExampleParsedJson_ForEach() { 1286 if !SupportedCPU() { 1287 // Fake results 1288 fmt.Println("Got iterator for type: object\nFound element: URL Type: string Value: http://example.com/example.gif") 1289 return 1290 } 1291 1292 // Parse JSON: 1293 pj, err := Parse([]byte(`{"Image":{"URL":"http://example.com/example.gif"}}`), nil) 1294 if err != nil { 1295 log.Fatal(err) 1296 } 1297 1298 // Create an element we can reuse. 1299 var element *Element 1300 err = pj.ForEach(func(i Iter) error { 1301 fmt.Println("Got iterator for type:", i.Type()) 1302 element, err = i.FindElement(element, "Image", "URL") 1303 if err == nil { 1304 value, _ := element.Iter.StringCvt() 1305 fmt.Println("Found element:", element.Name, "Type:", element.Type, "Value:", value) 1306 } 1307 return nil 1308 }) 1309 if err != nil { 1310 log.Fatal(err) 1311 } 1312 // Output: 1313 // Got iterator for type: object 1314 // Found element: URL Type: string Value: http://example.com/example.gif 1315 }