github.com/zhangdapeng520/zdpgo_json@v0.1.5/query/query.go (about) 1 package query 2 3 import ( 4 "encoding/json" 5 "strconv" 6 "strings" 7 "unicode/utf16" 8 "unicode/utf8" 9 "unsafe" 10 11 "github.com/zhangdapeng520/zdpgo_json/match" 12 "github.com/zhangdapeng520/zdpgo_json/pretty" 13 ) 14 15 // Query 查询核心对象 16 type Query struct { 17 // Get 根据路径从json字符串中查询数据 18 Get func(json, path string) Result 19 } 20 21 func NewQuery() *Query { 22 q := Query{} 23 24 // 实例化方法 25 q.Get = Get 26 27 return &q 28 } 29 30 // Get 查询指定路径的结果。结果应该是一个JSON数组或对象。 31 func (t Result) Get(path string) Result { 32 r := Get(t.Raw, path) 33 if r.Indexes != nil { 34 for i := 0; i < len(r.Indexes); i++ { 35 r.Indexes[i] += t.Index 36 } 37 } else { 38 r.Index += t.Index 39 } 40 return r 41 } 42 43 type arrayOrMapResult struct { 44 a []Result 45 ai []interface{} 46 o map[string]Result 47 oi map[string]interface{} 48 vc byte 49 } 50 51 func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) { 52 var json = t.Raw 53 var i int 54 var value Result 55 var count int 56 var key Result 57 if vc == 0 { 58 for ; i < len(json); i++ { 59 if json[i] == '{' || json[i] == '[' { 60 r.vc = json[i] 61 i++ 62 break 63 } 64 if json[i] > ' ' { 65 goto end 66 } 67 } 68 } else { 69 for ; i < len(json); i++ { 70 if json[i] == vc { 71 i++ 72 break 73 } 74 if json[i] > ' ' { 75 goto end 76 } 77 } 78 r.vc = vc 79 } 80 if r.vc == '{' { 81 if valueize { 82 r.oi = make(map[string]interface{}) 83 } else { 84 r.o = make(map[string]Result) 85 } 86 } else { 87 if valueize { 88 r.ai = make([]interface{}, 0) 89 } else { 90 r.a = make([]Result, 0) 91 } 92 } 93 for ; i < len(json); i++ { 94 if json[i] <= ' ' { 95 continue 96 } 97 // get next value 98 if json[i] == ']' || json[i] == '}' { 99 break 100 } 101 switch json[i] { 102 default: 103 if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' { 104 value.Type = Number 105 value.Raw, value.Num = tonum(json[i:]) 106 value.Str = "" 107 } else { 108 continue 109 } 110 case '{', '[': 111 value.Type = JSON 112 value.Raw = squash(json[i:]) 113 value.Str, value.Num = "", 0 114 case 'n': 115 value.Type = Null 116 value.Raw = tolit(json[i:]) 117 value.Str, value.Num = "", 0 118 case 't': 119 value.Type = True 120 value.Raw = tolit(json[i:]) 121 value.Str, value.Num = "", 0 122 case 'f': 123 value.Type = False 124 value.Raw = tolit(json[i:]) 125 value.Str, value.Num = "", 0 126 case '"': 127 value.Type = String 128 value.Raw, value.Str = tostr(json[i:]) 129 value.Num = 0 130 } 131 value.Index = i + t.Index 132 133 i += len(value.Raw) - 1 134 135 if r.vc == '{' { 136 if count%2 == 0 { 137 key = value 138 } else { 139 if valueize { 140 if _, ok := r.oi[key.Str]; !ok { 141 r.oi[key.Str] = value.Value() 142 } 143 } else { 144 if _, ok := r.o[key.Str]; !ok { 145 r.o[key.Str] = value 146 } 147 } 148 } 149 count++ 150 } else { 151 if valueize { 152 r.ai = append(r.ai, value.Value()) 153 } else { 154 r.a = append(r.a, value) 155 } 156 } 157 } 158 end: 159 if t.Indexes != nil { 160 if len(t.Indexes) != len(r.a) { 161 for i := 0; i < len(r.a); i++ { 162 r.a[i].Index = 0 163 } 164 } else { 165 for i := 0; i < len(r.a); i++ { 166 r.a[i].Index = t.Indexes[i] 167 } 168 } 169 } 170 return 171 } 172 173 // Parse 解析json并返回一个结果。 174 // 这个函数期望json是格式良好的,并且不进行验证。 175 // 无效的json将不会异常,但它可能返回意想不到的结果。 176 // 如果您使用的JSON来自一个不可预测的来源,那么您可能希望首先使用Valid函数。 177 func Parse(json string) Result { 178 var value Result 179 i := 0 180 for ; i < len(json); i++ { 181 if json[i] == '{' || json[i] == '[' { 182 value.Type = JSON 183 value.Raw = json[i:] // just take the entire raw 184 break 185 } 186 if json[i] <= ' ' { 187 continue 188 } 189 switch json[i] { 190 case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 191 'i', 'I', 'N': 192 value.Type = Number 193 value.Raw, value.Num = tonum(json[i:]) 194 case 'n': 195 if i+1 < len(json) && json[i+1] != 'u' { 196 // nan 197 value.Type = Number 198 value.Raw, value.Num = tonum(json[i:]) 199 } else { 200 // null 201 value.Type = Null 202 value.Raw = tolit(json[i:]) 203 } 204 case 't': 205 value.Type = True 206 value.Raw = tolit(json[i:]) 207 case 'f': 208 value.Type = False 209 value.Raw = tolit(json[i:]) 210 case '"': 211 value.Type = String 212 value.Raw, value.Str = tostr(json[i:]) 213 default: 214 return Result{} 215 } 216 break 217 } 218 if value.Exists() { 219 value.Index = i 220 } 221 return value 222 } 223 224 // ParseBytes 解析json并返回一个结果。如果使用字节,此方法优于Parse(string(data)) 225 func ParseBytes(json []byte) Result { 226 return Parse(string(json)) 227 } 228 229 func squash(json string) string { 230 // expects that the lead character is a '[' or '{' or '(' or '"' 231 // squash the value, ignoring all nested arrays and objects. 232 var i, depth int 233 if json[0] != '"' { 234 i, depth = 1, 1 235 } 236 for ; i < len(json); i++ { 237 if json[i] >= '"' && json[i] <= '}' { 238 switch json[i] { 239 case '"': 240 i++ 241 s2 := i 242 for ; i < len(json); i++ { 243 if json[i] > '\\' { 244 continue 245 } 246 if json[i] == '"' { 247 // look for an escaped slash 248 if json[i-1] == '\\' { 249 n := 0 250 for j := i - 2; j > s2-1; j-- { 251 if json[j] != '\\' { 252 break 253 } 254 n++ 255 } 256 if n%2 == 0 { 257 continue 258 } 259 } 260 break 261 } 262 } 263 if depth == 0 { 264 if i >= len(json) { 265 return json 266 } 267 return json[:i+1] 268 } 269 case '{', '[', '(': 270 depth++ 271 case '}', ']', ')': 272 depth-- 273 if depth == 0 { 274 return json[:i+1] 275 } 276 } 277 } 278 } 279 return json 280 } 281 282 func tonum(json string) (raw string, num float64) { 283 for i := 1; i < len(json); i++ { 284 // less than dash might have valid characters 285 if json[i] <= '-' { 286 if json[i] <= ' ' || json[i] == ',' { 287 // break on whitespace and comma 288 raw = json[:i] 289 num, _ = strconv.ParseFloat(raw, 64) 290 return 291 } 292 // could be a '+' or '-'. let's assume so. 293 } else if json[i] == ']' || json[i] == '}' { 294 // break on ']' or '}' 295 raw = json[:i] 296 num, _ = strconv.ParseFloat(raw, 64) 297 return 298 } 299 } 300 raw = json 301 num, _ = strconv.ParseFloat(raw, 64) 302 return 303 } 304 305 func tolit(json string) (raw string) { 306 for i := 1; i < len(json); i++ { 307 if json[i] < 'a' || json[i] > 'z' { 308 return json[:i] 309 } 310 } 311 return json 312 } 313 314 func tostr(json string) (raw string, str string) { 315 // expects that the lead character is a '"' 316 for i := 1; i < len(json); i++ { 317 if json[i] > '\\' { 318 continue 319 } 320 if json[i] == '"' { 321 return json[:i+1], json[1:i] 322 } 323 if json[i] == '\\' { 324 i++ 325 for ; i < len(json); i++ { 326 if json[i] > '\\' { 327 continue 328 } 329 if json[i] == '"' { 330 // look for an escaped slash 331 if json[i-1] == '\\' { 332 n := 0 333 for j := i - 2; j > 0; j-- { 334 if json[j] != '\\' { 335 break 336 } 337 n++ 338 } 339 if n%2 == 0 { 340 continue 341 } 342 } 343 return json[:i+1], unescape(json[1:i]) 344 } 345 } 346 var ret string 347 if i+1 < len(json) { 348 ret = json[:i+1] 349 } else { 350 ret = json[:i] 351 } 352 return ret, unescape(json[1:i]) 353 } 354 } 355 return json, json[1:] 356 } 357 358 func parseString(json string, i int) (int, string, bool, bool) { 359 var s = i 360 for ; i < len(json); i++ { 361 if json[i] > '\\' { 362 continue 363 } 364 if json[i] == '"' { 365 return i + 1, json[s-1 : i+1], false, true 366 } 367 if json[i] == '\\' { 368 i++ 369 for ; i < len(json); i++ { 370 if json[i] > '\\' { 371 continue 372 } 373 if json[i] == '"' { 374 // look for an escaped slash 375 if json[i-1] == '\\' { 376 n := 0 377 for j := i - 2; j > 0; j-- { 378 if json[j] != '\\' { 379 break 380 } 381 n++ 382 } 383 if n%2 == 0 { 384 continue 385 } 386 } 387 return i + 1, json[s-1 : i+1], true, true 388 } 389 } 390 break 391 } 392 } 393 return i, json[s-1:], false, false 394 } 395 396 func parseNumber(json string, i int) (int, string) { 397 var s = i 398 i++ 399 for ; i < len(json); i++ { 400 if json[i] <= ' ' || json[i] == ',' || json[i] == ']' || 401 json[i] == '}' { 402 return i, json[s:i] 403 } 404 } 405 return i, json[s:] 406 } 407 408 func parseLiteral(json string, i int) (int, string) { 409 var s = i 410 i++ 411 for ; i < len(json); i++ { 412 if json[i] < 'a' || json[i] > 'z' { 413 return i, json[s:i] 414 } 415 } 416 return i, json[s:] 417 } 418 419 type arrayPathResult struct { 420 part string 421 path string 422 pipe string 423 piped bool 424 more bool 425 alogok bool 426 arrch bool 427 alogkey string 428 query struct { 429 on bool 430 all bool 431 path string 432 op string 433 value string 434 } 435 } 436 437 func parseArrayPath(path string) (r arrayPathResult) { 438 for i := 0; i < len(path); i++ { 439 if path[i] == '|' { 440 r.part = path[:i] 441 r.pipe = path[i+1:] 442 r.piped = true 443 return 444 } 445 if path[i] == '.' { 446 r.part = path[:i] 447 if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) { 448 r.pipe = path[i+1:] 449 r.piped = true 450 } else { 451 r.path = path[i+1:] 452 r.more = true 453 } 454 return 455 } 456 if path[i] == '#' { 457 r.arrch = true 458 if i == 0 && len(path) > 1 { 459 if path[1] == '.' { 460 r.alogok = true 461 r.alogkey = path[2:] 462 r.path = path[:1] 463 } else if path[1] == '[' || path[1] == '(' { 464 // query 465 r.query.on = true 466 qpath, op, value, _, fi, vesc, ok := 467 parseQuery(path[i:]) 468 if !ok { 469 // bad query, end now 470 break 471 } 472 if len(value) >= 2 && value[0] == '"' && 473 value[len(value)-1] == '"' { 474 value = value[1 : len(value)-1] 475 if vesc { 476 value = unescape(value) 477 } 478 } 479 r.query.path = qpath 480 r.query.op = op 481 r.query.value = value 482 483 i = fi - 1 484 if i+1 < len(path) && path[i+1] == '#' { 485 r.query.all = true 486 } 487 } 488 } 489 continue 490 } 491 } 492 r.part = path 493 r.path = "" 494 return 495 } 496 497 // splitQuery接受一个查询并将其拆分为三个部分: 498 // path, op, middle, and right. 499 // So for this query: 500 // #(first_name=="Murphy").last 501 // Becomes 502 // first_name # path 503 // =="Murphy" # middle 504 // .last # right 505 // Or, 506 // #(service_roles.#(=="one")).cap 507 // Becomes 508 // service_roles.#(=="one") # path 509 // # middle 510 // .cap # right 511 func parseQuery(query string) ( 512 path, op, value, remain string, i int, vesc, ok bool, 513 ) { 514 if len(query) < 2 || query[0] != '#' || 515 (query[1] != '(' && query[1] != '[') { 516 return "", "", "", "", i, false, false 517 } 518 i = 2 519 j := 0 // start of value part 520 depth := 1 521 for ; i < len(query); i++ { 522 if depth == 1 && j == 0 { 523 switch query[i] { 524 case '!', '=', '<', '>', '%': 525 // start of the value part 526 j = i 527 continue 528 } 529 } 530 if query[i] == '\\' { 531 i++ 532 } else if query[i] == '[' || query[i] == '(' { 533 depth++ 534 } else if query[i] == ']' || query[i] == ')' { 535 depth-- 536 if depth == 0 { 537 break 538 } 539 } else if query[i] == '"' { 540 // inside selector string, balance quotes 541 i++ 542 for ; i < len(query); i++ { 543 if query[i] == '\\' { 544 vesc = true 545 i++ 546 } else if query[i] == '"' { 547 break 548 } 549 } 550 } 551 } 552 if depth > 0 { 553 return "", "", "", "", i, false, false 554 } 555 if j > 0 { 556 path = trim(query[2:j]) 557 value = trim(query[j:i]) 558 remain = query[i+1:] 559 // parse the compare op from the value 560 var opsz int 561 switch { 562 case len(value) == 1: 563 opsz = 1 564 case value[0] == '!' && value[1] == '=': 565 opsz = 2 566 case value[0] == '!' && value[1] == '%': 567 opsz = 2 568 case value[0] == '<' && value[1] == '=': 569 opsz = 2 570 case value[0] == '>' && value[1] == '=': 571 opsz = 2 572 case value[0] == '=' && value[1] == '=': 573 value = value[1:] 574 opsz = 1 575 case value[0] == '<': 576 opsz = 1 577 case value[0] == '>': 578 opsz = 1 579 case value[0] == '=': 580 opsz = 1 581 case value[0] == '%': 582 opsz = 1 583 } 584 op = value[:opsz] 585 value = trim(value[opsz:]) 586 } else { 587 path = trim(query[2:i]) 588 remain = query[i+1:] 589 } 590 return path, op, value, remain, i + 1, vesc, true 591 } 592 593 func trim(s string) string { 594 left: 595 if len(s) > 0 && s[0] <= ' ' { 596 s = s[1:] 597 goto left 598 } 599 right: 600 if len(s) > 0 && s[len(s)-1] <= ' ' { 601 s = s[:len(s)-1] 602 goto right 603 } 604 return s 605 } 606 607 // peek at the next byte and see if it's a '@', '[', or '{'. 608 func isDotPiperChar(c byte) bool { 609 return !DisableModifiers && (c == '@' || c == '[' || c == '{') 610 } 611 612 type objectPathResult struct { 613 part string 614 path string 615 pipe string 616 piped bool 617 wild bool 618 more bool 619 } 620 621 func parseObjectPath(path string) (r objectPathResult) { 622 for i := 0; i < len(path); i++ { 623 if path[i] == '|' { 624 r.part = path[:i] 625 r.pipe = path[i+1:] 626 r.piped = true 627 return 628 } 629 if path[i] == '.' { 630 r.part = path[:i] 631 if i < len(path)-1 && isDotPiperChar(path[i+1]) { 632 r.pipe = path[i+1:] 633 r.piped = true 634 } else { 635 r.path = path[i+1:] 636 r.more = true 637 } 638 return 639 } 640 if path[i] == '*' || path[i] == '?' { 641 r.wild = true 642 continue 643 } 644 if path[i] == '\\' { 645 // go into escape mode. this is a slower path that 646 // strips off the escape character from the part. 647 epart := []byte(path[:i]) 648 i++ 649 if i < len(path) { 650 epart = append(epart, path[i]) 651 i++ 652 for ; i < len(path); i++ { 653 if path[i] == '\\' { 654 i++ 655 if i < len(path) { 656 epart = append(epart, path[i]) 657 } 658 continue 659 } else if path[i] == '.' { 660 r.part = string(epart) 661 if i < len(path)-1 && isDotPiperChar(path[i+1]) { 662 r.pipe = path[i+1:] 663 r.piped = true 664 } else { 665 r.path = path[i+1:] 666 } 667 r.more = true 668 return 669 } else if path[i] == '|' { 670 r.part = string(epart) 671 r.pipe = path[i+1:] 672 r.piped = true 673 return 674 } else if path[i] == '*' || path[i] == '?' { 675 r.wild = true 676 } 677 epart = append(epart, path[i]) 678 } 679 } 680 // append the last part 681 r.part = string(epart) 682 return 683 } 684 } 685 r.part = path 686 return 687 } 688 689 func parseSquash(json string, i int) (int, string) { 690 // expects that the lead character is a '[' or '{' or '(' 691 // squash the value, ignoring all nested arrays and objects. 692 // the first '[' or '{' or '(' has already been read 693 s := i 694 i++ 695 depth := 1 696 for ; i < len(json); i++ { 697 if json[i] >= '"' && json[i] <= '}' { 698 switch json[i] { 699 case '"': 700 i++ 701 s2 := i 702 for ; i < len(json); i++ { 703 if json[i] > '\\' { 704 continue 705 } 706 if json[i] == '"' { 707 // look for an escaped slash 708 if json[i-1] == '\\' { 709 n := 0 710 for j := i - 2; j > s2-1; j-- { 711 if json[j] != '\\' { 712 break 713 } 714 n++ 715 } 716 if n%2 == 0 { 717 continue 718 } 719 } 720 break 721 } 722 } 723 case '{', '[', '(': 724 depth++ 725 case '}', ']', ')': 726 depth-- 727 if depth == 0 { 728 i++ 729 return i, json[s:i] 730 } 731 } 732 } 733 } 734 return i, json[s:] 735 } 736 737 func parseObject(c *parseContext, i int, path string) (int, bool) { 738 var pmatch, kesc, vesc, ok, hit bool 739 var key, val string 740 rp := parseObjectPath(path) 741 if !rp.more && rp.piped { 742 c.pipe = rp.pipe 743 c.piped = true 744 } 745 for i < len(c.json) { 746 for ; i < len(c.json); i++ { 747 if c.json[i] == '"' { 748 // parse_key_string 749 // this is slightly different from getting s string value 750 // because we don't need the outer quotes. 751 i++ 752 var s = i 753 for ; i < len(c.json); i++ { 754 if c.json[i] > '\\' { 755 continue 756 } 757 if c.json[i] == '"' { 758 i, key, kesc, ok = i+1, c.json[s:i], false, true 759 goto parse_key_string_done 760 } 761 if c.json[i] == '\\' { 762 i++ 763 for ; i < len(c.json); i++ { 764 if c.json[i] > '\\' { 765 continue 766 } 767 if c.json[i] == '"' { 768 // look for an escaped slash 769 if c.json[i-1] == '\\' { 770 n := 0 771 for j := i - 2; j > 0; j-- { 772 if c.json[j] != '\\' { 773 break 774 } 775 n++ 776 } 777 if n%2 == 0 { 778 continue 779 } 780 } 781 i, key, kesc, ok = i+1, c.json[s:i], true, true 782 goto parse_key_string_done 783 } 784 } 785 break 786 } 787 } 788 key, kesc, ok = c.json[s:], false, false 789 parse_key_string_done: 790 break 791 } 792 if c.json[i] == '}' { 793 return i + 1, false 794 } 795 } 796 if !ok { 797 return i, false 798 } 799 if rp.wild { 800 if kesc { 801 pmatch = matchLimit(unescape(key), rp.part) 802 } else { 803 pmatch = matchLimit(key, rp.part) 804 } 805 } else { 806 if kesc { 807 pmatch = rp.part == unescape(key) 808 } else { 809 pmatch = rp.part == key 810 } 811 } 812 hit = pmatch && !rp.more 813 for ; i < len(c.json); i++ { 814 var num bool 815 switch c.json[i] { 816 default: 817 continue 818 case '"': 819 i++ 820 i, val, vesc, ok = parseString(c.json, i) 821 if !ok { 822 return i, false 823 } 824 if hit { 825 if vesc { 826 c.value.Str = unescape(val[1 : len(val)-1]) 827 } else { 828 c.value.Str = val[1 : len(val)-1] 829 } 830 c.value.Raw = val 831 c.value.Type = String 832 return i, true 833 } 834 case '{': 835 if pmatch && !hit { 836 i, hit = parseObject(c, i+1, rp.path) 837 if hit { 838 return i, true 839 } 840 } else { 841 i, val = parseSquash(c.json, i) 842 if hit { 843 c.value.Raw = val 844 c.value.Type = JSON 845 return i, true 846 } 847 } 848 case '[': 849 if pmatch && !hit { 850 i, hit = parseArray(c, i+1, rp.path) 851 if hit { 852 return i, true 853 } 854 } else { 855 i, val = parseSquash(c.json, i) 856 if hit { 857 c.value.Raw = val 858 c.value.Type = JSON 859 return i, true 860 } 861 } 862 case 'n': 863 if i+1 < len(c.json) && c.json[i+1] != 'u' { 864 num = true 865 break 866 } 867 fallthrough 868 case 't', 'f': 869 vc := c.json[i] 870 i, val = parseLiteral(c.json, i) 871 if hit { 872 c.value.Raw = val 873 switch vc { 874 case 't': 875 c.value.Type = True 876 case 'f': 877 c.value.Type = False 878 } 879 return i, true 880 } 881 case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 882 'i', 'I', 'N': 883 num = true 884 } 885 if num { 886 i, val = parseNumber(c.json, i) 887 if hit { 888 c.value.Raw = val 889 c.value.Type = Number 890 c.value.Num, _ = strconv.ParseFloat(val, 64) 891 return i, true 892 } 893 } 894 break 895 } 896 } 897 return i, false 898 } 899 900 // matchLimit will limit the complexity of the match operation to avoid ReDos 901 // attacks from arbritary inputs. 902 // See the github.com/tidwall/match.MatchLimit function for more information. 903 func matchLimit(str, pattern string) bool { 904 matched, _ := match.MatchLimit(str, pattern, 10000) 905 return matched 906 } 907 908 func queryMatches(rp *arrayPathResult, value Result) bool { 909 rpv := rp.query.value 910 if len(rpv) > 0 && rpv[0] == '~' { 911 // convert to bool 912 rpv = rpv[1:] 913 if value.Bool() { 914 value = Result{Type: True} 915 } else { 916 value = Result{Type: False} 917 } 918 } 919 if !value.Exists() { 920 return false 921 } 922 if rp.query.op == "" { 923 // the query is only looking for existence, such as: 924 // friends.#(name) 925 // which makes sure that the array "friends" has an element of 926 // "name" that exists 927 return true 928 } 929 switch value.Type { 930 case String: 931 switch rp.query.op { 932 case "=": 933 return value.Str == rpv 934 case "!=": 935 return value.Str != rpv 936 case "<": 937 return value.Str < rpv 938 case "<=": 939 return value.Str <= rpv 940 case ">": 941 return value.Str > rpv 942 case ">=": 943 return value.Str >= rpv 944 case "%": 945 return matchLimit(value.Str, rpv) 946 case "!%": 947 return !matchLimit(value.Str, rpv) 948 } 949 case Number: 950 rpvn, _ := strconv.ParseFloat(rpv, 64) 951 switch rp.query.op { 952 case "=": 953 return value.Num == rpvn 954 case "!=": 955 return value.Num != rpvn 956 case "<": 957 return value.Num < rpvn 958 case "<=": 959 return value.Num <= rpvn 960 case ">": 961 return value.Num > rpvn 962 case ">=": 963 return value.Num >= rpvn 964 } 965 case True: 966 switch rp.query.op { 967 case "=": 968 return rpv == "true" 969 case "!=": 970 return rpv != "true" 971 case ">": 972 return rpv == "false" 973 case ">=": 974 return true 975 } 976 case False: 977 switch rp.query.op { 978 case "=": 979 return rpv == "false" 980 case "!=": 981 return rpv != "false" 982 case "<": 983 return rpv == "true" 984 case "<=": 985 return true 986 } 987 } 988 return false 989 } 990 func parseArray(c *parseContext, i int, path string) (int, bool) { 991 var pmatch, vesc, ok, hit bool 992 var val string 993 var h int 994 var alog []int 995 var partidx int 996 var multires []byte 997 var queryIndexes []int 998 rp := parseArrayPath(path) 999 if !rp.arrch { 1000 n, ok := parseUint(rp.part) 1001 if !ok { 1002 partidx = -1 1003 } else { 1004 partidx = int(n) 1005 } 1006 } 1007 if !rp.more && rp.piped { 1008 c.pipe = rp.pipe 1009 c.piped = true 1010 } 1011 1012 procQuery := func(qval Result) bool { 1013 if rp.query.all { 1014 if len(multires) == 0 { 1015 multires = append(multires, '[') 1016 } 1017 } 1018 var tmp parseContext 1019 tmp.value = qval 1020 fillIndex(c.json, &tmp) 1021 parentIndex := tmp.value.Index 1022 var res Result 1023 if qval.Type == JSON { 1024 res = qval.Get(rp.query.path) 1025 } else { 1026 if rp.query.path != "" { 1027 return false 1028 } 1029 res = qval 1030 } 1031 if queryMatches(&rp, res) { 1032 if rp.more { 1033 left, right, ok := splitPossiblePipe(rp.path) 1034 if ok { 1035 rp.path = left 1036 c.pipe = right 1037 c.piped = true 1038 } 1039 res = qval.Get(rp.path) 1040 } else { 1041 res = qval 1042 } 1043 if rp.query.all { 1044 raw := res.Raw 1045 if len(raw) == 0 { 1046 raw = res.String() 1047 } 1048 if raw != "" { 1049 if len(multires) > 1 { 1050 multires = append(multires, ',') 1051 } 1052 multires = append(multires, raw...) 1053 queryIndexes = append(queryIndexes, res.Index+parentIndex) 1054 } 1055 } else { 1056 c.value = res 1057 return true 1058 } 1059 } 1060 return false 1061 } 1062 for i < len(c.json)+1 { 1063 if !rp.arrch { 1064 pmatch = partidx == h 1065 hit = pmatch && !rp.more 1066 } 1067 h++ 1068 if rp.alogok { 1069 alog = append(alog, i) 1070 } 1071 for ; ; i++ { 1072 var ch byte 1073 if i > len(c.json) { 1074 break 1075 } else if i == len(c.json) { 1076 ch = ']' 1077 } else { 1078 ch = c.json[i] 1079 } 1080 var num bool 1081 switch ch { 1082 default: 1083 continue 1084 case '"': 1085 i++ 1086 i, val, vesc, ok = parseString(c.json, i) 1087 if !ok { 1088 return i, false 1089 } 1090 if rp.query.on { 1091 var qval Result 1092 if vesc { 1093 qval.Str = unescape(val[1 : len(val)-1]) 1094 } else { 1095 qval.Str = val[1 : len(val)-1] 1096 } 1097 qval.Raw = val 1098 qval.Type = String 1099 if procQuery(qval) { 1100 return i, true 1101 } 1102 } else if hit { 1103 if rp.alogok { 1104 break 1105 } 1106 if vesc { 1107 c.value.Str = unescape(val[1 : len(val)-1]) 1108 } else { 1109 c.value.Str = val[1 : len(val)-1] 1110 } 1111 c.value.Raw = val 1112 c.value.Type = String 1113 return i, true 1114 } 1115 case '{': 1116 if pmatch && !hit { 1117 i, hit = parseObject(c, i+1, rp.path) 1118 if hit { 1119 if rp.alogok { 1120 break 1121 } 1122 return i, true 1123 } 1124 } else { 1125 i, val = parseSquash(c.json, i) 1126 if rp.query.on { 1127 if procQuery(Result{Raw: val, Type: JSON}) { 1128 return i, true 1129 } 1130 } else if hit { 1131 if rp.alogok { 1132 break 1133 } 1134 c.value.Raw = val 1135 c.value.Type = JSON 1136 return i, true 1137 } 1138 } 1139 case '[': 1140 if pmatch && !hit { 1141 i, hit = parseArray(c, i+1, rp.path) 1142 if hit { 1143 if rp.alogok { 1144 break 1145 } 1146 return i, true 1147 } 1148 } else { 1149 i, val = parseSquash(c.json, i) 1150 if rp.query.on { 1151 if procQuery(Result{Raw: val, Type: JSON}) { 1152 return i, true 1153 } 1154 } else if hit { 1155 if rp.alogok { 1156 break 1157 } 1158 c.value.Raw = val 1159 c.value.Type = JSON 1160 return i, true 1161 } 1162 } 1163 case 'n': 1164 if i+1 < len(c.json) && c.json[i+1] != 'u' { 1165 num = true 1166 break 1167 } 1168 fallthrough 1169 case 't', 'f': 1170 vc := c.json[i] 1171 i, val = parseLiteral(c.json, i) 1172 if rp.query.on { 1173 var qval Result 1174 qval.Raw = val 1175 switch vc { 1176 case 't': 1177 qval.Type = True 1178 case 'f': 1179 qval.Type = False 1180 } 1181 if procQuery(qval) { 1182 return i, true 1183 } 1184 } else if hit { 1185 if rp.alogok { 1186 break 1187 } 1188 c.value.Raw = val 1189 switch vc { 1190 case 't': 1191 c.value.Type = True 1192 case 'f': 1193 c.value.Type = False 1194 } 1195 return i, true 1196 } 1197 case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 1198 'i', 'I', 'N': 1199 num = true 1200 case ']': 1201 if rp.arrch && rp.part == "#" { 1202 if rp.alogok { 1203 left, right, ok := splitPossiblePipe(rp.alogkey) 1204 if ok { 1205 rp.alogkey = left 1206 c.pipe = right 1207 c.piped = true 1208 } 1209 var indexes = make([]int, 0, 64) 1210 var jsons = make([]byte, 0, 64) 1211 jsons = append(jsons, '[') 1212 for j, k := 0, 0; j < len(alog); j++ { 1213 idx := alog[j] 1214 for idx < len(c.json) { 1215 switch c.json[idx] { 1216 case ' ', '\t', '\r', '\n': 1217 idx++ 1218 continue 1219 } 1220 break 1221 } 1222 if idx < len(c.json) && c.json[idx] != ']' { 1223 _, res, ok := parseAny(c.json, idx, true) 1224 if ok { 1225 res := res.Get(rp.alogkey) 1226 if res.Exists() { 1227 if k > 0 { 1228 jsons = append(jsons, ',') 1229 } 1230 raw := res.Raw 1231 if len(raw) == 0 { 1232 raw = res.String() 1233 } 1234 jsons = append(jsons, []byte(raw)...) 1235 indexes = append(indexes, res.Index) 1236 k++ 1237 } 1238 } 1239 } 1240 } 1241 jsons = append(jsons, ']') 1242 c.value.Type = JSON 1243 c.value.Raw = string(jsons) 1244 c.value.Indexes = indexes 1245 return i + 1, true 1246 } 1247 if rp.alogok { 1248 break 1249 } 1250 1251 c.value.Type = Number 1252 c.value.Num = float64(h - 1) 1253 c.value.Raw = strconv.Itoa(h - 1) 1254 c.calcd = true 1255 return i + 1, true 1256 } 1257 if !c.value.Exists() { 1258 if len(multires) > 0 { 1259 c.value = Result{ 1260 Raw: string(append(multires, ']')), 1261 Type: JSON, 1262 Indexes: queryIndexes, 1263 } 1264 } else if rp.query.all { 1265 c.value = Result{ 1266 Raw: "[]", 1267 Type: JSON, 1268 } 1269 } 1270 } 1271 return i + 1, false 1272 } 1273 if num { 1274 i, val = parseNumber(c.json, i) 1275 if rp.query.on { 1276 var qval Result 1277 qval.Raw = val 1278 qval.Type = Number 1279 qval.Num, _ = strconv.ParseFloat(val, 64) 1280 if procQuery(qval) { 1281 return i, true 1282 } 1283 } else if hit { 1284 if rp.alogok { 1285 break 1286 } 1287 c.value.Raw = val 1288 c.value.Type = Number 1289 c.value.Num, _ = strconv.ParseFloat(val, 64) 1290 return i, true 1291 } 1292 } 1293 break 1294 } 1295 } 1296 return i, false 1297 } 1298 1299 func splitPossiblePipe(path string) (left, right string, ok bool) { 1300 // take a quick peek for the pipe character. If found we'll split the piped 1301 // part of the path into the c.pipe field and shorten the rp. 1302 var possible bool 1303 for i := 0; i < len(path); i++ { 1304 if path[i] == '|' { 1305 possible = true 1306 break 1307 } 1308 } 1309 if !possible { 1310 return 1311 } 1312 1313 if len(path) > 0 && path[0] == '{' { 1314 squashed := squash(path[1:]) 1315 if len(squashed) < len(path)-1 { 1316 squashed = path[:len(squashed)+1] 1317 remain := path[len(squashed):] 1318 if remain[0] == '|' { 1319 return squashed, remain[1:], true 1320 } 1321 } 1322 return 1323 } 1324 1325 // split the left and right side of the path with the pipe character as 1326 // the delimiter. This is a little tricky because we'll need to basically 1327 // parse the entire path. 1328 for i := 0; i < len(path); i++ { 1329 if path[i] == '\\' { 1330 i++ 1331 } else if path[i] == '.' { 1332 if i == len(path)-1 { 1333 return 1334 } 1335 if path[i+1] == '#' { 1336 i += 2 1337 if i == len(path) { 1338 return 1339 } 1340 if path[i] == '[' || path[i] == '(' { 1341 var start, end byte 1342 if path[i] == '[' { 1343 start, end = '[', ']' 1344 } else { 1345 start, end = '(', ')' 1346 } 1347 // inside selector, balance brackets 1348 i++ 1349 depth := 1 1350 for ; i < len(path); i++ { 1351 if path[i] == '\\' { 1352 i++ 1353 } else if path[i] == start { 1354 depth++ 1355 } else if path[i] == end { 1356 depth-- 1357 if depth == 0 { 1358 break 1359 } 1360 } else if path[i] == '"' { 1361 // inside selector string, balance quotes 1362 i++ 1363 for ; i < len(path); i++ { 1364 if path[i] == '\\' { 1365 i++ 1366 } else if path[i] == '"' { 1367 break 1368 } 1369 } 1370 } 1371 } 1372 } 1373 } 1374 } else if path[i] == '|' { 1375 return path[:i], path[i+1:], true 1376 } 1377 } 1378 return 1379 } 1380 1381 // ForEachLine 通过JSON lines指定的JSON行进行迭代 1382 func ForEachLine(json string, iterator func(line Result) bool) { 1383 var res Result 1384 var i int 1385 for { 1386 i, res, _ = parseAny(json, i, true) 1387 if !res.Exists() { 1388 break 1389 } 1390 if !iterator(res) { 1391 return 1392 } 1393 } 1394 } 1395 1396 type subSelector struct { 1397 name string 1398 path string 1399 } 1400 1401 // parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or 1402 // '{"field1":path1,"field2":path2}' type subSelection. It's expected that the 1403 // first character in path is either '[' or '{', and has already been checked 1404 // prior to calling this function. 1405 func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) { 1406 modifier := 0 1407 depth := 1 1408 colon := 0 1409 start := 1 1410 i := 1 1411 pushSel := func() { 1412 var sel subSelector 1413 if colon == 0 { 1414 sel.path = path[start:i] 1415 } else { 1416 sel.name = path[start:colon] 1417 sel.path = path[colon+1 : i] 1418 } 1419 sels = append(sels, sel) 1420 colon = 0 1421 modifier = 0 1422 start = i + 1 1423 } 1424 for ; i < len(path); i++ { 1425 switch path[i] { 1426 case '\\': 1427 i++ 1428 case '@': 1429 if modifier == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') { 1430 modifier = i 1431 } 1432 case ':': 1433 if modifier == 0 && colon == 0 && depth == 1 { 1434 colon = i 1435 } 1436 case ',': 1437 if depth == 1 { 1438 pushSel() 1439 } 1440 case '"': 1441 i++ 1442 loop: 1443 for ; i < len(path); i++ { 1444 switch path[i] { 1445 case '\\': 1446 i++ 1447 case '"': 1448 break loop 1449 } 1450 } 1451 case '[', '(', '{': 1452 depth++ 1453 case ']', ')', '}': 1454 depth-- 1455 if depth == 0 { 1456 pushSel() 1457 path = path[i+1:] 1458 return sels, path, true 1459 } 1460 } 1461 } 1462 return 1463 } 1464 1465 // nameOfLast returns the name of the last component 1466 func nameOfLast(path string) string { 1467 for i := len(path) - 1; i >= 0; i-- { 1468 if path[i] == '|' || path[i] == '.' { 1469 if i > 0 { 1470 if path[i-1] == '\\' { 1471 continue 1472 } 1473 } 1474 return path[i+1:] 1475 } 1476 } 1477 return path 1478 } 1479 1480 func isSimpleName(component string) bool { 1481 for i := 0; i < len(component); i++ { 1482 if component[i] < ' ' { 1483 return false 1484 } 1485 switch component[i] { 1486 case '[', ']', '{', '}', '(', ')', '#', '|', '!': 1487 return false 1488 } 1489 } 1490 return true 1491 } 1492 1493 func appendJSONString(dst []byte, s string) []byte { 1494 for i := 0; i < len(s); i++ { 1495 if s[i] < ' ' || s[i] == '\\' || s[i] == '"' || s[i] > 126 { 1496 d, _ := json.Marshal(s) 1497 return append(dst, string(d)...) 1498 } 1499 } 1500 dst = append(dst, '"') 1501 dst = append(dst, s...) 1502 dst = append(dst, '"') 1503 return dst 1504 } 1505 1506 type parseContext struct { 1507 json string 1508 value Result 1509 pipe string 1510 piped bool 1511 calcd bool 1512 lines bool 1513 } 1514 1515 // Get 在json中搜索指定路径。 1516 // 路径使用.分割,比如:"name.last" 或 "age" 1517 // 当找到值时,它会立即返回。 1518 func Get(json, path string) Result { 1519 if len(path) > 1 { 1520 if (path[0] == '@' && !DisableModifiers) || path[0] == '!' { 1521 // possible modifier 1522 var ok bool 1523 var npath string 1524 var rjson string 1525 if path[0] == '@' && !DisableModifiers { 1526 npath, rjson, ok = execModifier(json, path) 1527 } else if path[0] == '!' { 1528 npath, rjson, ok = execStatic(json, path) 1529 } 1530 if ok { 1531 path = npath 1532 if len(path) > 0 && (path[0] == '|' || path[0] == '.') { 1533 res := Get(rjson, path[1:]) 1534 res.Index = 0 1535 res.Indexes = nil 1536 return res 1537 } 1538 return Parse(rjson) 1539 } 1540 } 1541 1542 // 查询数组 1543 if path[0] == '[' || path[0] == '{' { 1544 // using a subselector path 1545 kind := path[0] 1546 var ok bool 1547 var subs []subSelector 1548 subs, path, ok = parseSubSelectors(path) 1549 if ok { 1550 if len(path) == 0 || (path[0] == '|' || path[0] == '.') { 1551 var b []byte 1552 b = append(b, kind) 1553 var i int 1554 for _, sub := range subs { 1555 res := Get(json, sub.path) 1556 if res.Exists() { 1557 if i > 0 { 1558 b = append(b, ',') 1559 } 1560 if kind == '{' { 1561 if len(sub.name) > 0 { 1562 if sub.name[0] == '"' && Valid(sub.name) { 1563 b = append(b, sub.name...) 1564 } else { 1565 b = appendJSONString(b, sub.name) 1566 } 1567 } else { 1568 last := nameOfLast(sub.path) 1569 if isSimpleName(last) { 1570 b = appendJSONString(b, last) 1571 } else { 1572 b = appendJSONString(b, "_") 1573 } 1574 } 1575 b = append(b, ':') 1576 } 1577 var raw string 1578 if len(res.Raw) == 0 { 1579 raw = res.String() 1580 if len(raw) == 0 { 1581 raw = "null" 1582 } 1583 } else { 1584 raw = res.Raw 1585 } 1586 b = append(b, raw...) 1587 i++ 1588 } 1589 } 1590 b = append(b, kind+2) 1591 var res Result 1592 res.Raw = string(b) 1593 res.Type = JSON 1594 if len(path) > 0 { 1595 res = res.Get(path[1:]) 1596 } 1597 res.Index = 0 1598 return res 1599 } 1600 } 1601 } 1602 } 1603 var i int 1604 var c = &parseContext{json: json} 1605 if len(path) >= 2 && path[0] == '.' && path[1] == '.' { 1606 c.lines = true 1607 parseArray(c, 0, path[2:]) 1608 } else { 1609 for ; i < len(c.json); i++ { 1610 if c.json[i] == '{' { 1611 i++ 1612 parseObject(c, i, path) 1613 break 1614 } 1615 if c.json[i] == '[' { 1616 i++ 1617 parseArray(c, i, path) 1618 break 1619 } 1620 } 1621 } 1622 if c.piped { 1623 res := c.value.Get(c.pipe) 1624 res.Index = 0 1625 return res 1626 } 1627 fillIndex(json, c) 1628 return c.value 1629 } 1630 1631 // GetBytes 在json中搜索指定路径。 1632 // 如果使用字节,此方法优于Get(string(data), path) 1633 func GetBytes(json []byte, path string) Result { 1634 return getBytes(json, path) 1635 } 1636 1637 // runeit returns the rune from the the \uXXXX 1638 func runeit(json string) rune { 1639 n, _ := strconv.ParseUint(json[:4], 16, 64) 1640 return rune(n) 1641 } 1642 1643 // unescape unescapes a string 1644 func unescape(json string) string { 1645 var str = make([]byte, 0, len(json)) 1646 for i := 0; i < len(json); i++ { 1647 switch { 1648 default: 1649 str = append(str, json[i]) 1650 case json[i] < ' ': 1651 return string(str) 1652 case json[i] == '\\': 1653 i++ 1654 if i >= len(json) { 1655 return string(str) 1656 } 1657 switch json[i] { 1658 default: 1659 return string(str) 1660 case '\\': 1661 str = append(str, '\\') 1662 case '/': 1663 str = append(str, '/') 1664 case 'b': 1665 str = append(str, '\b') 1666 case 'f': 1667 str = append(str, '\f') 1668 case 'n': 1669 str = append(str, '\n') 1670 case 'r': 1671 str = append(str, '\r') 1672 case 't': 1673 str = append(str, '\t') 1674 case '"': 1675 str = append(str, '"') 1676 case 'u': 1677 if i+5 > len(json) { 1678 return string(str) 1679 } 1680 r := runeit(json[i+1:]) 1681 i += 5 1682 if utf16.IsSurrogate(r) { 1683 // need another code 1684 if len(json[i:]) >= 6 && json[i] == '\\' && 1685 json[i+1] == 'u' { 1686 // we expect it to be correct so just consume it 1687 r = utf16.DecodeRune(r, runeit(json[i+2:])) 1688 i += 6 1689 } 1690 } 1691 // provide enough space to encode the largest utf8 possible 1692 str = append(str, 0, 0, 0, 0, 0, 0, 0, 0) 1693 n := utf8.EncodeRune(str[len(str)-8:], r) 1694 str = str[:len(str)-8+n] 1695 i-- // backtrack index by one 1696 } 1697 } 1698 } 1699 return string(str) 1700 } 1701 1702 // Less 如果一个令牌小于另一个令牌,则返回true。 1703 // 当令牌为string时,使用caseSensitive参数。比较两种不同类型时的顺序为: 1704 // Null < False < Number < String < True < JSON 1705 func (t Result) Less(token Result, caseSensitive bool) bool { 1706 if t.Type < token.Type { 1707 return true 1708 } 1709 if t.Type > token.Type { 1710 return false 1711 } 1712 if t.Type == String { 1713 if caseSensitive { 1714 return t.Str < token.Str 1715 } 1716 return stringLessInsensitive(t.Str, token.Str) 1717 } 1718 if t.Type == Number { 1719 return t.Num < token.Num 1720 } 1721 return t.Raw < token.Raw 1722 } 1723 1724 func stringLessInsensitive(a, b string) bool { 1725 for i := 0; i < len(a) && i < len(b); i++ { 1726 if a[i] >= 'A' && a[i] <= 'Z' { 1727 if b[i] >= 'A' && b[i] <= 'Z' { 1728 // both are uppercase, do nothing 1729 if a[i] < b[i] { 1730 return true 1731 } else if a[i] > b[i] { 1732 return false 1733 } 1734 } else { 1735 // a is uppercase, convert a to lowercase 1736 if a[i]+32 < b[i] { 1737 return true 1738 } else if a[i]+32 > b[i] { 1739 return false 1740 } 1741 } 1742 } else if b[i] >= 'A' && b[i] <= 'Z' { 1743 // b is uppercase, convert b to lowercase 1744 if a[i] < b[i]+32 { 1745 return true 1746 } else if a[i] > b[i]+32 { 1747 return false 1748 } 1749 } else { 1750 // neither are uppercase 1751 if a[i] < b[i] { 1752 return true 1753 } else if a[i] > b[i] { 1754 return false 1755 } 1756 } 1757 } 1758 return len(a) < len(b) 1759 } 1760 1761 // parseAny parses the next value from a json string. 1762 // A Result is returned when the hit param is set. 1763 // The return values are (i int, res Result, ok bool) 1764 func parseAny(json string, i int, hit bool) (int, Result, bool) { 1765 var res Result 1766 var val string 1767 for ; i < len(json); i++ { 1768 if json[i] == '{' || json[i] == '[' { 1769 i, val = parseSquash(json, i) 1770 if hit { 1771 res.Raw = val 1772 res.Type = JSON 1773 } 1774 var tmp parseContext 1775 tmp.value = res 1776 fillIndex(json, &tmp) 1777 return i, tmp.value, true 1778 } 1779 if json[i] <= ' ' { 1780 continue 1781 } 1782 var num bool 1783 switch json[i] { 1784 case '"': 1785 i++ 1786 var vesc bool 1787 var ok bool 1788 i, val, vesc, ok = parseString(json, i) 1789 if !ok { 1790 return i, res, false 1791 } 1792 if hit { 1793 res.Type = String 1794 res.Raw = val 1795 if vesc { 1796 res.Str = unescape(val[1 : len(val)-1]) 1797 } else { 1798 res.Str = val[1 : len(val)-1] 1799 } 1800 } 1801 return i, res, true 1802 case 'n': 1803 if i+1 < len(json) && json[i+1] != 'u' { 1804 num = true 1805 break 1806 } 1807 fallthrough 1808 case 't', 'f': 1809 vc := json[i] 1810 i, val = parseLiteral(json, i) 1811 if hit { 1812 res.Raw = val 1813 switch vc { 1814 case 't': 1815 res.Type = True 1816 case 'f': 1817 res.Type = False 1818 } 1819 return i, res, true 1820 } 1821 case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 1822 'i', 'I', 'N': 1823 num = true 1824 } 1825 if num { 1826 i, val = parseNumber(json, i) 1827 if hit { 1828 res.Raw = val 1829 res.Type = Number 1830 res.Num, _ = strconv.ParseFloat(val, 64) 1831 } 1832 return i, res, true 1833 } 1834 1835 } 1836 return i, res, false 1837 } 1838 1839 // GetMany 在json中搜索多个路径。 1840 // 返回值是一个Result数组,其中项的数量将等于输入路径的数量。 1841 func GetMany(json string, path ...string) []Result { 1842 res := make([]Result, len(path)) 1843 for i, path := range path { 1844 res[i] = Get(json, path) 1845 } 1846 return res 1847 } 1848 1849 // GetManyBytes 在json中搜索多个路径 1850 // 返回值是一个Result数组,其中项的数量将等于输入路径的数量。 1851 func GetManyBytes(json []byte, path ...string) []Result { 1852 res := make([]Result, len(path)) 1853 for i, path := range path { 1854 res[i] = GetBytes(json, path) 1855 } 1856 return res 1857 } 1858 1859 func validpayload(data []byte, i int) (outi int, ok bool) { 1860 for ; i < len(data); i++ { 1861 switch data[i] { 1862 default: 1863 i, ok = validany(data, i) 1864 if !ok { 1865 return i, false 1866 } 1867 for ; i < len(data); i++ { 1868 switch data[i] { 1869 default: 1870 return i, false 1871 case ' ', '\t', '\n', '\r': 1872 continue 1873 } 1874 } 1875 return i, true 1876 case ' ', '\t', '\n', '\r': 1877 continue 1878 } 1879 } 1880 return i, false 1881 } 1882 func validany(data []byte, i int) (outi int, ok bool) { 1883 for ; i < len(data); i++ { 1884 switch data[i] { 1885 default: 1886 return i, false 1887 case ' ', '\t', '\n', '\r': 1888 continue 1889 case '{': 1890 return validobject(data, i+1) 1891 case '[': 1892 return validarray(data, i+1) 1893 case '"': 1894 return validstring(data, i+1) 1895 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 1896 return validnumber(data, i+1) 1897 case 't': 1898 return validtrue(data, i+1) 1899 case 'f': 1900 return validfalse(data, i+1) 1901 case 'n': 1902 return validnull(data, i+1) 1903 } 1904 } 1905 return i, false 1906 } 1907 func validobject(data []byte, i int) (outi int, ok bool) { 1908 for ; i < len(data); i++ { 1909 switch data[i] { 1910 default: 1911 return i, false 1912 case ' ', '\t', '\n', '\r': 1913 continue 1914 case '}': 1915 return i + 1, true 1916 case '"': 1917 key: 1918 if i, ok = validstring(data, i+1); !ok { 1919 return i, false 1920 } 1921 if i, ok = validcolon(data, i); !ok { 1922 return i, false 1923 } 1924 if i, ok = validany(data, i); !ok { 1925 return i, false 1926 } 1927 if i, ok = validcomma(data, i, '}'); !ok { 1928 return i, false 1929 } 1930 if data[i] == '}' { 1931 return i + 1, true 1932 } 1933 i++ 1934 for ; i < len(data); i++ { 1935 switch data[i] { 1936 default: 1937 return i, false 1938 case ' ', '\t', '\n', '\r': 1939 continue 1940 case '"': 1941 goto key 1942 } 1943 } 1944 return i, false 1945 } 1946 } 1947 return i, false 1948 } 1949 func validcolon(data []byte, i int) (outi int, ok bool) { 1950 for ; i < len(data); i++ { 1951 switch data[i] { 1952 default: 1953 return i, false 1954 case ' ', '\t', '\n', '\r': 1955 continue 1956 case ':': 1957 return i + 1, true 1958 } 1959 } 1960 return i, false 1961 } 1962 func validcomma(data []byte, i int, end byte) (outi int, ok bool) { 1963 for ; i < len(data); i++ { 1964 switch data[i] { 1965 default: 1966 return i, false 1967 case ' ', '\t', '\n', '\r': 1968 continue 1969 case ',': 1970 return i, true 1971 case end: 1972 return i, true 1973 } 1974 } 1975 return i, false 1976 } 1977 func validarray(data []byte, i int) (outi int, ok bool) { 1978 for ; i < len(data); i++ { 1979 switch data[i] { 1980 default: 1981 for ; i < len(data); i++ { 1982 if i, ok = validany(data, i); !ok { 1983 return i, false 1984 } 1985 if i, ok = validcomma(data, i, ']'); !ok { 1986 return i, false 1987 } 1988 if data[i] == ']' { 1989 return i + 1, true 1990 } 1991 } 1992 case ' ', '\t', '\n', '\r': 1993 continue 1994 case ']': 1995 return i + 1, true 1996 } 1997 } 1998 return i, false 1999 } 2000 func validstring(data []byte, i int) (outi int, ok bool) { 2001 for ; i < len(data); i++ { 2002 if data[i] < ' ' { 2003 return i, false 2004 } else if data[i] == '\\' { 2005 i++ 2006 if i == len(data) { 2007 return i, false 2008 } 2009 switch data[i] { 2010 default: 2011 return i, false 2012 case '"', '\\', '/', 'b', 'f', 'n', 'r', 't': 2013 case 'u': 2014 for j := 0; j < 4; j++ { 2015 i++ 2016 if i >= len(data) { 2017 return i, false 2018 } 2019 if !((data[i] >= '0' && data[i] <= '9') || 2020 (data[i] >= 'a' && data[i] <= 'f') || 2021 (data[i] >= 'A' && data[i] <= 'F')) { 2022 return i, false 2023 } 2024 } 2025 } 2026 } else if data[i] == '"' { 2027 return i + 1, true 2028 } 2029 } 2030 return i, false 2031 } 2032 func validnumber(data []byte, i int) (outi int, ok bool) { 2033 i-- 2034 // sign 2035 if data[i] == '-' { 2036 i++ 2037 if i == len(data) { 2038 return i, false 2039 } 2040 if data[i] < '0' || data[i] > '9' { 2041 return i, false 2042 } 2043 } 2044 // int 2045 if i == len(data) { 2046 return i, false 2047 } 2048 if data[i] == '0' { 2049 i++ 2050 } else { 2051 for ; i < len(data); i++ { 2052 if data[i] >= '0' && data[i] <= '9' { 2053 continue 2054 } 2055 break 2056 } 2057 } 2058 // frac 2059 if i == len(data) { 2060 return i, true 2061 } 2062 if data[i] == '.' { 2063 i++ 2064 if i == len(data) { 2065 return i, false 2066 } 2067 if data[i] < '0' || data[i] > '9' { 2068 return i, false 2069 } 2070 i++ 2071 for ; i < len(data); i++ { 2072 if data[i] >= '0' && data[i] <= '9' { 2073 continue 2074 } 2075 break 2076 } 2077 } 2078 // exp 2079 if i == len(data) { 2080 return i, true 2081 } 2082 if data[i] == 'e' || data[i] == 'E' { 2083 i++ 2084 if i == len(data) { 2085 return i, false 2086 } 2087 if data[i] == '+' || data[i] == '-' { 2088 i++ 2089 } 2090 if i == len(data) { 2091 return i, false 2092 } 2093 if data[i] < '0' || data[i] > '9' { 2094 return i, false 2095 } 2096 i++ 2097 for ; i < len(data); i++ { 2098 if data[i] >= '0' && data[i] <= '9' { 2099 continue 2100 } 2101 break 2102 } 2103 } 2104 return i, true 2105 } 2106 2107 func validtrue(data []byte, i int) (outi int, ok bool) { 2108 if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' && 2109 data[i+2] == 'e' { 2110 return i + 3, true 2111 } 2112 return i, false 2113 } 2114 func validfalse(data []byte, i int) (outi int, ok bool) { 2115 if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' && 2116 data[i+2] == 's' && data[i+3] == 'e' { 2117 return i + 4, true 2118 } 2119 return i, false 2120 } 2121 func validnull(data []byte, i int) (outi int, ok bool) { 2122 if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' && 2123 data[i+2] == 'l' { 2124 return i + 3, true 2125 } 2126 return i, false 2127 } 2128 2129 // Valid 如果输入的json是有效的,返回true。 2130 func Valid(json string) bool { 2131 _, ok := validpayload(stringBytes(json), 0) 2132 return ok 2133 } 2134 2135 // ValidBytes 如果输入的json是有效的,返回true。 2136 func ValidBytes(json []byte) bool { 2137 _, ok := validpayload(json, 0) 2138 return ok 2139 } 2140 2141 func parseUint(s string) (n uint64, ok bool) { 2142 var i int 2143 if i == len(s) { 2144 return 0, false 2145 } 2146 for ; i < len(s); i++ { 2147 if s[i] >= '0' && s[i] <= '9' { 2148 n = n*10 + uint64(s[i]-'0') 2149 } else { 2150 return 0, false 2151 } 2152 } 2153 return n, true 2154 } 2155 2156 func parseInt(s string) (n int64, ok bool) { 2157 var i int 2158 var sign bool 2159 if len(s) > 0 && s[0] == '-' { 2160 sign = true 2161 i++ 2162 } 2163 if i == len(s) { 2164 return 0, false 2165 } 2166 for ; i < len(s); i++ { 2167 if s[i] >= '0' && s[i] <= '9' { 2168 n = n*10 + int64(s[i]-'0') 2169 } else { 2170 return 0, false 2171 } 2172 } 2173 if sign { 2174 return n * -1, true 2175 } 2176 return n, true 2177 } 2178 2179 // safeInt 验证给定的JSON编号,确保它位于最小和最大可表示的JSON编号内 2180 func safeInt(f float64) (n int64, ok bool) { 2181 // https://tc39.es/ecma262/#sec-number.min_safe_integer 2182 // https://tc39.es/ecma262/#sec-number.max_safe_integer 2183 if f < -9007199254740991 || f > 9007199254740991 { 2184 return 0, false 2185 } 2186 return int64(f), true 2187 } 2188 2189 // execStatic parses the path to find a static value. 2190 // The input expects that the path already starts with a '!' 2191 func execStatic(json, path string) (pathOut, res string, ok bool) { 2192 name := path[1:] 2193 if len(name) > 0 { 2194 switch name[0] { 2195 case '{', '[', '"', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', 2196 '8', '9': 2197 _, res = parseSquash(name, 0) 2198 pathOut = name[len(res):] 2199 return pathOut, res, true 2200 } 2201 } 2202 for i := 1; i < len(path); i++ { 2203 if path[i] == '|' { 2204 pathOut = path[i:] 2205 name = path[1:i] 2206 break 2207 } 2208 if path[i] == '.' { 2209 pathOut = path[i:] 2210 name = path[1:i] 2211 break 2212 } 2213 } 2214 switch strings.ToLower(name) { 2215 case "true", "false", "null", "nan", "inf": 2216 return pathOut, name, true 2217 } 2218 return pathOut, res, false 2219 } 2220 2221 // execModifier parses the path to find a matching modifier function. 2222 // The input expects that the path already starts with a '@' 2223 func execModifier(json, path string) (pathOut, res string, ok bool) { 2224 name := path[1:] 2225 var hasArgs bool 2226 for i := 1; i < len(path); i++ { 2227 if path[i] == ':' { 2228 pathOut = path[i+1:] 2229 name = path[1:i] 2230 hasArgs = len(pathOut) > 0 2231 break 2232 } 2233 if path[i] == '|' { 2234 pathOut = path[i:] 2235 name = path[1:i] 2236 break 2237 } 2238 if path[i] == '.' { 2239 pathOut = path[i:] 2240 name = path[1:i] 2241 break 2242 } 2243 } 2244 if fn, ok := modifiers[name]; ok { 2245 var args string 2246 if hasArgs { 2247 var parsedArgs bool 2248 switch pathOut[0] { 2249 case '{', '[', '"': 2250 res := Parse(pathOut) 2251 if res.Exists() { 2252 args = squash(pathOut) 2253 pathOut = pathOut[len(args):] 2254 parsedArgs = true 2255 } 2256 } 2257 if !parsedArgs { 2258 idx := strings.IndexByte(pathOut, '|') 2259 if idx == -1 { 2260 args = pathOut 2261 pathOut = "" 2262 } else { 2263 args = pathOut[:idx] 2264 pathOut = pathOut[idx:] 2265 } 2266 } 2267 } 2268 return pathOut, fn(json, args), true 2269 } 2270 return pathOut, res, false 2271 } 2272 2273 // unwrap removes the '[]' or '{}' characters around json 2274 func unwrap(json string) string { 2275 json = trim(json) 2276 if len(json) >= 2 && (json[0] == '[' || json[0] == '{') { 2277 json = json[1 : len(json)-1] 2278 } 2279 return json 2280 } 2281 2282 // DisableModifiers will disable the modifier syntax 2283 var DisableModifiers = false 2284 2285 var modifiers = map[string]func(json, arg string) string{ 2286 "pretty": modPretty, 2287 "ugly": modUgly, 2288 "reverse": modReverse, 2289 "this": modThis, 2290 "flatten": modFlatten, 2291 "join": modJoin, 2292 "valid": modValid, 2293 "keys": modKeys, 2294 "values": modValues, 2295 } 2296 2297 // AddModifier 将一个自定义修饰符命令绑定到GJSON语法。 2298 // 这个操作不是线程安全的,应该在使用所有其他查询函数之前执行。 2299 func AddModifier(name string, fn func(json, arg string) string) { 2300 modifiers[name] = fn 2301 } 2302 2303 // ModifierExists 当指定的修饰符存在时返回true。 2304 func ModifierExists(name string, fn func(json, arg string) string) bool { 2305 _, ok := modifiers[name] 2306 return ok 2307 } 2308 2309 // cleanWS remove any non-whitespace from string 2310 func cleanWS(s string) string { 2311 for i := 0; i < len(s); i++ { 2312 switch s[i] { 2313 case ' ', '\t', '\n', '\r': 2314 continue 2315 default: 2316 var s2 []byte 2317 for i := 0; i < len(s); i++ { 2318 switch s[i] { 2319 case ' ', '\t', '\n', '\r': 2320 s2 = append(s2, s[i]) 2321 } 2322 } 2323 return string(s2) 2324 } 2325 } 2326 return s 2327 } 2328 2329 // @pretty modifier makes the json look nice. 2330 func modPretty(json, arg string) string { 2331 if len(arg) > 0 { 2332 opts := *pretty.DefaultOptions 2333 Parse(arg).ForEach(func(key, value Result) bool { 2334 switch key.String() { 2335 case "sortKeys": 2336 opts.SortKeys = value.Bool() 2337 case "indent": 2338 opts.Indent = cleanWS(value.String()) 2339 case "prefix": 2340 opts.Prefix = cleanWS(value.String()) 2341 case "width": 2342 opts.Width = int(value.Int()) 2343 } 2344 return true 2345 }) 2346 return bytesString(pretty.PrettyOptions(stringBytes(json), &opts)) 2347 } 2348 return bytesString(pretty.Pretty(stringBytes(json))) 2349 } 2350 2351 // @this returns the current element. Can be used to retrieve the root element. 2352 func modThis(json, arg string) string { 2353 return json 2354 } 2355 2356 // @ugly modifier removes all whitespace. 2357 func modUgly(json, arg string) string { 2358 return bytesString(pretty.Ugly(stringBytes(json))) 2359 } 2360 2361 // @reverse reverses array elements or root object members. 2362 func modReverse(json, arg string) string { 2363 res := Parse(json) 2364 if res.IsArray() { 2365 var values []Result 2366 res.ForEach(func(_, value Result) bool { 2367 values = append(values, value) 2368 return true 2369 }) 2370 out := make([]byte, 0, len(json)) 2371 out = append(out, '[') 2372 for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 { 2373 if j > 0 { 2374 out = append(out, ',') 2375 } 2376 out = append(out, values[i].Raw...) 2377 } 2378 out = append(out, ']') 2379 return bytesString(out) 2380 } 2381 if res.IsObject() { 2382 var keyValues []Result 2383 res.ForEach(func(key, value Result) bool { 2384 keyValues = append(keyValues, key, value) 2385 return true 2386 }) 2387 out := make([]byte, 0, len(json)) 2388 out = append(out, '{') 2389 for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 { 2390 if j > 0 { 2391 out = append(out, ',') 2392 } 2393 out = append(out, keyValues[i+0].Raw...) 2394 out = append(out, ':') 2395 out = append(out, keyValues[i+1].Raw...) 2396 } 2397 out = append(out, '}') 2398 return bytesString(out) 2399 } 2400 return json 2401 } 2402 2403 // @flatten an array with child arrays. 2404 // [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]] 2405 // The {"deep":true} arg can be provide for deep flattening. 2406 // [1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7] 2407 // The original json is returned when the json is not an array. 2408 func modFlatten(json, arg string) string { 2409 res := Parse(json) 2410 if !res.IsArray() { 2411 return json 2412 } 2413 var deep bool 2414 if arg != "" { 2415 Parse(arg).ForEach(func(key, value Result) bool { 2416 if key.String() == "deep" { 2417 deep = value.Bool() 2418 } 2419 return true 2420 }) 2421 } 2422 var out []byte 2423 out = append(out, '[') 2424 var idx int 2425 res.ForEach(func(_, value Result) bool { 2426 var raw string 2427 if value.IsArray() { 2428 if deep { 2429 raw = unwrap(modFlatten(value.Raw, arg)) 2430 } else { 2431 raw = unwrap(value.Raw) 2432 } 2433 } else { 2434 raw = value.Raw 2435 } 2436 raw = strings.TrimSpace(raw) 2437 if len(raw) > 0 { 2438 if idx > 0 { 2439 out = append(out, ',') 2440 } 2441 out = append(out, raw...) 2442 idx++ 2443 } 2444 return true 2445 }) 2446 out = append(out, ']') 2447 return bytesString(out) 2448 } 2449 2450 // @keys extracts the keys from an object. 2451 // {"first":"Tom","last":"Smith"} -> ["first","last"] 2452 func modKeys(json, arg string) string { 2453 v := Parse(json) 2454 if !v.Exists() { 2455 return "[]" 2456 } 2457 obj := v.IsObject() 2458 var out strings.Builder 2459 out.WriteByte('[') 2460 var i int 2461 v.ForEach(func(key, _ Result) bool { 2462 if i > 0 { 2463 out.WriteByte(',') 2464 } 2465 if obj { 2466 out.WriteString(key.Raw) 2467 } else { 2468 out.WriteString("null") 2469 } 2470 i++ 2471 return true 2472 }) 2473 out.WriteByte(']') 2474 return out.String() 2475 } 2476 2477 // @values extracts the values from an object. 2478 // {"first":"Tom","last":"Smith"} -> ["Tom","Smith"] 2479 func modValues(json, arg string) string { 2480 v := Parse(json) 2481 if !v.Exists() { 2482 return "[]" 2483 } 2484 if v.IsArray() { 2485 return json 2486 } 2487 var out strings.Builder 2488 out.WriteByte('[') 2489 var i int 2490 v.ForEach(func(_, value Result) bool { 2491 if i > 0 { 2492 out.WriteByte(',') 2493 } 2494 out.WriteString(value.Raw) 2495 i++ 2496 return true 2497 }) 2498 out.WriteByte(']') 2499 return out.String() 2500 } 2501 2502 // @join multiple objects into a single object. 2503 // [{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"} 2504 // The arg can be "true" to specify that duplicate keys should be preserved. 2505 // [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41} 2506 // Without preserved keys: 2507 // [{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41} 2508 // The original json is returned when the json is not an object. 2509 func modJoin(json, arg string) string { 2510 res := Parse(json) 2511 if !res.IsArray() { 2512 return json 2513 } 2514 var preserve bool 2515 if arg != "" { 2516 Parse(arg).ForEach(func(key, value Result) bool { 2517 if key.String() == "preserve" { 2518 preserve = value.Bool() 2519 } 2520 return true 2521 }) 2522 } 2523 var out []byte 2524 out = append(out, '{') 2525 if preserve { 2526 // Preserve duplicate keys. 2527 var idx int 2528 res.ForEach(func(_, value Result) bool { 2529 if !value.IsObject() { 2530 return true 2531 } 2532 if idx > 0 { 2533 out = append(out, ',') 2534 } 2535 out = append(out, unwrap(value.Raw)...) 2536 idx++ 2537 return true 2538 }) 2539 } else { 2540 // Deduplicate keys and generate an object with stable ordering. 2541 var keys []Result 2542 kvals := make(map[string]Result) 2543 res.ForEach(func(_, value Result) bool { 2544 if !value.IsObject() { 2545 return true 2546 } 2547 value.ForEach(func(key, value Result) bool { 2548 k := key.String() 2549 if _, ok := kvals[k]; !ok { 2550 keys = append(keys, key) 2551 } 2552 kvals[k] = value 2553 return true 2554 }) 2555 return true 2556 }) 2557 for i := 0; i < len(keys); i++ { 2558 if i > 0 { 2559 out = append(out, ',') 2560 } 2561 out = append(out, keys[i].Raw...) 2562 out = append(out, ':') 2563 out = append(out, kvals[keys[i].String()].Raw...) 2564 } 2565 } 2566 out = append(out, '}') 2567 return bytesString(out) 2568 } 2569 2570 // @valid ensures that the json is valid before moving on. An empty string is 2571 // returned when the json is not valid, otherwise it returns the original json. 2572 func modValid(json, arg string) string { 2573 if !Valid(json) { 2574 return "" 2575 } 2576 return json 2577 } 2578 2579 // stringHeader instead of reflect.StringHeader 2580 type stringHeader struct { 2581 data unsafe.Pointer 2582 len int 2583 } 2584 2585 // sliceHeader instead of reflect.SliceHeader 2586 type sliceHeader struct { 2587 data unsafe.Pointer 2588 len int 2589 cap int 2590 } 2591 2592 // getBytes casts the input json bytes to a string and safely returns the 2593 // results as uniquely allocated data. This operation is intended to minimize 2594 // copies and allocations for the large json string->[]byte. 2595 func getBytes(json []byte, path string) Result { 2596 var result Result 2597 if json != nil { 2598 // unsafe cast to string 2599 result = Get(*(*string)(unsafe.Pointer(&json)), path) 2600 // safely get the string headers 2601 rawhi := *(*stringHeader)(unsafe.Pointer(&result.Raw)) 2602 strhi := *(*stringHeader)(unsafe.Pointer(&result.Str)) 2603 // create byte slice headers 2604 rawh := sliceHeader{data: rawhi.data, len: rawhi.len, cap: rawhi.len} 2605 strh := sliceHeader{data: strhi.data, len: strhi.len, cap: rawhi.len} 2606 if strh.data == nil { 2607 // str is nil 2608 if rawh.data == nil { 2609 // raw is nil 2610 result.Raw = "" 2611 } else { 2612 // raw has data, safely copy the slice header to a string 2613 result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh))) 2614 } 2615 result.Str = "" 2616 } else if rawh.data == nil { 2617 // raw is nil 2618 result.Raw = "" 2619 // str has data, safely copy the slice header to a string 2620 result.Str = string(*(*[]byte)(unsafe.Pointer(&strh))) 2621 } else if uintptr(strh.data) >= uintptr(rawh.data) && 2622 uintptr(strh.data)+uintptr(strh.len) <= 2623 uintptr(rawh.data)+uintptr(rawh.len) { 2624 // Str is a substring of Raw. 2625 start := uintptr(strh.data) - uintptr(rawh.data) 2626 // safely copy the raw slice header 2627 result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh))) 2628 // substring the raw 2629 result.Str = result.Raw[start : start+uintptr(strh.len)] 2630 } else { 2631 // safely copy both the raw and str slice headers to strings 2632 result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh))) 2633 result.Str = string(*(*[]byte)(unsafe.Pointer(&strh))) 2634 } 2635 } 2636 return result 2637 } 2638 2639 // fillIndex finds the position of Raw data and assigns it to the Index field 2640 // of the resulting value. If the position cannot be found then Index zero is 2641 // used instead. 2642 func fillIndex(json string, c *parseContext) { 2643 if len(c.value.Raw) > 0 && !c.calcd { 2644 jhdr := *(*stringHeader)(unsafe.Pointer(&json)) 2645 rhdr := *(*stringHeader)(unsafe.Pointer(&(c.value.Raw))) 2646 c.value.Index = int(uintptr(rhdr.data) - uintptr(jhdr.data)) 2647 if c.value.Index < 0 || c.value.Index >= len(json) { 2648 c.value.Index = 0 2649 } 2650 } 2651 } 2652 2653 func stringBytes(s string) []byte { 2654 return *(*[]byte)(unsafe.Pointer(&sliceHeader{ 2655 data: (*stringHeader)(unsafe.Pointer(&s)).data, 2656 len: len(s), 2657 cap: len(s), 2658 })) 2659 } 2660 2661 func bytesString(b []byte) string { 2662 return *(*string)(unsafe.Pointer(&b)) 2663 } 2664 2665 func revSquash(json string) string { 2666 // reverse squash 2667 // expects that the tail character is a ']' or '}' or ')' or '"' 2668 // squash the value, ignoring all nested arrays and objects. 2669 i := len(json) - 1 2670 var depth int 2671 if json[i] != '"' { 2672 depth++ 2673 } 2674 if json[i] == '}' || json[i] == ']' || json[i] == ')' { 2675 i-- 2676 } 2677 for ; i >= 0; i-- { 2678 switch json[i] { 2679 case '"': 2680 i-- 2681 for ; i >= 0; i-- { 2682 if json[i] == '"' { 2683 esc := 0 2684 for i > 0 && json[i-1] == '\\' { 2685 i-- 2686 esc++ 2687 } 2688 if esc%2 == 1 { 2689 continue 2690 } 2691 i += esc 2692 break 2693 } 2694 } 2695 if depth == 0 { 2696 if i < 0 { 2697 i = 0 2698 } 2699 return json[i:] 2700 } 2701 case '}', ']', ')': 2702 depth++ 2703 case '{', '[', '(': 2704 depth-- 2705 if depth == 0 { 2706 return json[i:] 2707 } 2708 } 2709 } 2710 return json 2711 } 2712 2713 func (t Result) Paths(json string) []string { 2714 if t.Indexes == nil { 2715 return nil 2716 } 2717 paths := make([]string, 0, len(t.Indexes)) 2718 t.ForEach(func(_, value Result) bool { 2719 paths = append(paths, value.Path(json)) 2720 return true 2721 }) 2722 if len(paths) != len(t.Indexes) { 2723 return nil 2724 } 2725 return paths 2726 } 2727 2728 // Path returns the original GJSON path for Result. 2729 // The json param must be the original JSON used when calling Get. 2730 func (t Result) Path(json string) string { 2731 var path []byte 2732 var comps []string // raw components 2733 i := t.Index - 1 2734 if t.Index+len(t.Raw) > len(json) { 2735 // JSON cannot safely contain Result. 2736 goto fail 2737 } 2738 if !strings.HasPrefix(json[t.Index:], t.Raw) { 2739 // Result is not at the JSON index as exepcted. 2740 goto fail 2741 } 2742 for ; i >= 0; i-- { 2743 if json[i] <= ' ' { 2744 continue 2745 } 2746 if json[i] == ':' { 2747 // inside of object, get the key 2748 for ; i >= 0; i-- { 2749 if json[i] != '"' { 2750 continue 2751 } 2752 break 2753 } 2754 raw := revSquash(json[:i+1]) 2755 i = i - len(raw) 2756 comps = append(comps, raw) 2757 // key gotten, now squash the rest 2758 raw = revSquash(json[:i+1]) 2759 i = i - len(raw) 2760 i++ // increment the index for next loop step 2761 } else if json[i] == '{' { 2762 // Encountered an open object. The original result was probably an 2763 // object key. 2764 goto fail 2765 } else if json[i] == ',' || json[i] == '[' { 2766 // inside of an array, count the position 2767 var arrIdx int 2768 if json[i] == ',' { 2769 arrIdx++ 2770 i-- 2771 } 2772 for ; i >= 0; i-- { 2773 if json[i] == ':' { 2774 // Encountered an unexpected colon. The original result was 2775 // probably an object key. 2776 goto fail 2777 } else if json[i] == ',' { 2778 arrIdx++ 2779 } else if json[i] == '[' { 2780 comps = append(comps, strconv.Itoa(arrIdx)) 2781 break 2782 } else if json[i] == ']' || json[i] == '}' || json[i] == '"' { 2783 raw := revSquash(json[:i+1]) 2784 i = i - len(raw) + 1 2785 } 2786 } 2787 } 2788 } 2789 if len(comps) == 0 { 2790 if DisableModifiers { 2791 goto fail 2792 } 2793 return "@this" 2794 } 2795 for i := len(comps) - 1; i >= 0; i-- { 2796 rcomp := Parse(comps[i]) 2797 if !rcomp.Exists() { 2798 goto fail 2799 } 2800 comp := escapeComp(rcomp.String()) 2801 path = append(path, '.') 2802 path = append(path, comp...) 2803 } 2804 if len(path) > 0 { 2805 path = path[1:] 2806 } 2807 return string(path) 2808 fail: 2809 return "" 2810 } 2811 2812 // isSafePathKeyChar returns true if the input character is safe for not 2813 // needing escaping. 2814 func isSafePathKeyChar(c byte) bool { 2815 return c <= ' ' || c > '~' || c == '_' || c == '-' || c == ':' || 2816 (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || 2817 (c >= '0' && c <= '9') 2818 } 2819 2820 // escapeComp escaped a path compontent, making it safe for generating a 2821 // path for later use. 2822 func escapeComp(comp string) string { 2823 for i := 0; i < len(comp); i++ { 2824 if !isSafePathKeyChar(comp[i]) { 2825 ncomp := []byte(comp[:i]) 2826 for ; i < len(comp); i++ { 2827 if !isSafePathKeyChar(comp[i]) { 2828 ncomp = append(ncomp, '\\') 2829 } 2830 ncomp = append(ncomp, comp[i]) 2831 } 2832 return string(ncomp) 2833 } 2834 } 2835 return comp 2836 }