gjson.go

   1// Package gjson provides searching for json strings.
   2package gjson
   3
   4import (
   5	"strconv"
   6	"strings"
   7	"time"
   8	"unicode/utf16"
   9	"unicode/utf8"
  10	"unsafe"
  11
  12	"github.com/tidwall/match"
  13	"github.com/tidwall/pretty"
  14)
  15
  16// Type is Result type
  17type Type int
  18
  19const (
  20	// Null is a null json value
  21	Null Type = iota
  22	// False is a json false boolean
  23	False
  24	// Number is json number
  25	Number
  26	// String is a json string
  27	String
  28	// True is a json true boolean
  29	True
  30	// JSON is a raw block of JSON
  31	JSON
  32)
  33
  34// String returns a string representation of the type.
  35func (t Type) String() string {
  36	switch t {
  37	default:
  38		return ""
  39	case Null:
  40		return "Null"
  41	case False:
  42		return "False"
  43	case Number:
  44		return "Number"
  45	case String:
  46		return "String"
  47	case True:
  48		return "True"
  49	case JSON:
  50		return "JSON"
  51	}
  52}
  53
  54// Result represents a json value that is returned from Get().
  55type Result struct {
  56	// Type is the json type
  57	Type Type
  58	// Raw is the raw json
  59	Raw string
  60	// Str is the json string
  61	Str string
  62	// Num is the json number
  63	Num float64
  64	// Index of raw value in original json, zero means index unknown
  65	Index int
  66	// Indexes of all the elements that match on a path containing the '#'
  67	// query character.
  68	Indexes []int
  69}
  70
  71// String returns a string representation of the value.
  72func (t Result) String() string {
  73	switch t.Type {
  74	default:
  75		return ""
  76	case False:
  77		return "false"
  78	case Number:
  79		if len(t.Raw) == 0 {
  80			// calculated result
  81			return strconv.FormatFloat(t.Num, 'f', -1, 64)
  82		}
  83		var i int
  84		if t.Raw[0] == '-' {
  85			i++
  86		}
  87		for ; i < len(t.Raw); i++ {
  88			if t.Raw[i] < '0' || t.Raw[i] > '9' {
  89				return strconv.FormatFloat(t.Num, 'f', -1, 64)
  90			}
  91		}
  92		return t.Raw
  93	case String:
  94		return t.Str
  95	case JSON:
  96		return t.Raw
  97	case True:
  98		return "true"
  99	}
 100}
 101
 102// Bool returns an boolean representation.
 103func (t Result) Bool() bool {
 104	switch t.Type {
 105	default:
 106		return false
 107	case True:
 108		return true
 109	case String:
 110		b, _ := strconv.ParseBool(strings.ToLower(t.Str))
 111		return b
 112	case Number:
 113		return t.Num != 0
 114	}
 115}
 116
 117// Int returns an integer representation.
 118func (t Result) Int() int64 {
 119	switch t.Type {
 120	default:
 121		return 0
 122	case True:
 123		return 1
 124	case String:
 125		n, _ := parseInt(t.Str)
 126		return n
 127	case Number:
 128		// try to directly convert the float64 to int64
 129		i, ok := safeInt(t.Num)
 130		if ok {
 131			return i
 132		}
 133		// now try to parse the raw string
 134		i, ok = parseInt(t.Raw)
 135		if ok {
 136			return i
 137		}
 138		// fallback to a standard conversion
 139		return int64(t.Num)
 140	}
 141}
 142
 143// Uint returns an unsigned integer representation.
 144func (t Result) Uint() uint64 {
 145	switch t.Type {
 146	default:
 147		return 0
 148	case True:
 149		return 1
 150	case String:
 151		n, _ := parseUint(t.Str)
 152		return n
 153	case Number:
 154		// try to directly convert the float64 to uint64
 155		i, ok := safeInt(t.Num)
 156		if ok && i >= 0 {
 157			return uint64(i)
 158		}
 159		// now try to parse the raw string
 160		u, ok := parseUint(t.Raw)
 161		if ok {
 162			return u
 163		}
 164		// fallback to a standard conversion
 165		return uint64(t.Num)
 166	}
 167}
 168
 169// Float returns an float64 representation.
 170func (t Result) Float() float64 {
 171	switch t.Type {
 172	default:
 173		return 0
 174	case True:
 175		return 1
 176	case String:
 177		n, _ := strconv.ParseFloat(t.Str, 64)
 178		return n
 179	case Number:
 180		return t.Num
 181	}
 182}
 183
 184// Time returns a time.Time representation.
 185func (t Result) Time() time.Time {
 186	res, _ := time.Parse(time.RFC3339, t.String())
 187	return res
 188}
 189
 190// Array returns back an array of values.
 191// If the result represents a null value or is non-existent, then an empty
 192// array will be returned.
 193// If the result is not a JSON array, the return value will be an
 194// array containing one result.
 195func (t Result) Array() []Result {
 196	if t.Type == Null {
 197		return []Result{}
 198	}
 199	if !t.IsArray() {
 200		return []Result{t}
 201	}
 202	r := t.arrayOrMap('[', false)
 203	return r.a
 204}
 205
 206// IsObject returns true if the result value is a JSON object.
 207func (t Result) IsObject() bool {
 208	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '{'
 209}
 210
 211// IsArray returns true if the result value is a JSON array.
 212func (t Result) IsArray() bool {
 213	return t.Type == JSON && len(t.Raw) > 0 && t.Raw[0] == '['
 214}
 215
 216// IsBool returns true if the result value is a JSON boolean.
 217func (t Result) IsBool() bool {
 218	return t.Type == True || t.Type == False
 219}
 220
 221// ForEach iterates through values.
 222// If the result represents a non-existent value, then no values will be
 223// iterated. If the result is an Object, the iterator will pass the key and
 224// value of each item. If the result is an Array, the iterator will only pass
 225// the value of each item. If the result is not a JSON array or object, the
 226// iterator will pass back one value equal to the result.
 227func (t Result) ForEach(iterator func(key, value Result) bool) {
 228	if !t.Exists() {
 229		return
 230	}
 231	if t.Type != JSON {
 232		iterator(Result{}, t)
 233		return
 234	}
 235	json := t.Raw
 236	var obj bool
 237	var i int
 238	var key, value Result
 239	for ; i < len(json); i++ {
 240		if json[i] == '{' {
 241			i++
 242			key.Type = String
 243			obj = true
 244			break
 245		} else if json[i] == '[' {
 246			i++
 247			key.Type = Number
 248			key.Num = -1
 249			break
 250		}
 251		if json[i] > ' ' {
 252			return
 253		}
 254	}
 255	var str string
 256	var vesc bool
 257	var ok bool
 258	var idx int
 259	for ; i < len(json); i++ {
 260		if obj {
 261			if json[i] != '"' {
 262				continue
 263			}
 264			s := i
 265			i, str, vesc, ok = parseString(json, i+1)
 266			if !ok {
 267				return
 268			}
 269			if vesc {
 270				key.Str = unescape(str[1 : len(str)-1])
 271			} else {
 272				key.Str = str[1 : len(str)-1]
 273			}
 274			key.Raw = str
 275			key.Index = s + t.Index
 276		} else {
 277			key.Num += 1
 278		}
 279		for ; i < len(json); i++ {
 280			if json[i] <= ' ' || json[i] == ',' || json[i] == ':' {
 281				continue
 282			}
 283			break
 284		}
 285		s := i
 286		i, value, ok = parseAny(json, i, true)
 287		if !ok {
 288			return
 289		}
 290		if t.Indexes != nil {
 291			if idx < len(t.Indexes) {
 292				value.Index = t.Indexes[idx]
 293			}
 294		} else {
 295			value.Index = s + t.Index
 296		}
 297		if !iterator(key, value) {
 298			return
 299		}
 300		idx++
 301	}
 302}
 303
 304// Map returns back a map of values. The result should be a JSON object.
 305// If the result is not a JSON object, the return value will be an empty map.
 306func (t Result) Map() map[string]Result {
 307	if t.Type != JSON {
 308		return map[string]Result{}
 309	}
 310	r := t.arrayOrMap('{', false)
 311	return r.o
 312}
 313
 314// Get searches result for the specified path.
 315// The result should be a JSON array or object.
 316func (t Result) Get(path string) Result {
 317	r := Get(t.Raw, path)
 318	if r.Indexes != nil {
 319		for i := 0; i < len(r.Indexes); i++ {
 320			r.Indexes[i] += t.Index
 321		}
 322	} else {
 323		r.Index += t.Index
 324	}
 325	return r
 326}
 327
 328type arrayOrMapResult struct {
 329	a  []Result
 330	ai []interface{}
 331	o  map[string]Result
 332	oi map[string]interface{}
 333	vc byte
 334}
 335
 336func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
 337	var json = t.Raw
 338	var i int
 339	var value Result
 340	var count int
 341	var key Result
 342	if vc == 0 {
 343		for ; i < len(json); i++ {
 344			if json[i] == '{' || json[i] == '[' {
 345				r.vc = json[i]
 346				i++
 347				break
 348			}
 349			if json[i] > ' ' {
 350				goto end
 351			}
 352		}
 353	} else {
 354		for ; i < len(json); i++ {
 355			if json[i] == vc {
 356				i++
 357				break
 358			}
 359			if json[i] > ' ' {
 360				goto end
 361			}
 362		}
 363		r.vc = vc
 364	}
 365	if r.vc == '{' {
 366		if valueize {
 367			r.oi = make(map[string]interface{})
 368		} else {
 369			r.o = make(map[string]Result)
 370		}
 371	} else {
 372		if valueize {
 373			r.ai = make([]interface{}, 0)
 374		} else {
 375			r.a = make([]Result, 0)
 376		}
 377	}
 378	for ; i < len(json); i++ {
 379		if json[i] <= ' ' {
 380			continue
 381		}
 382		// get next value
 383		if json[i] == ']' || json[i] == '}' {
 384			break
 385		}
 386		switch json[i] {
 387		default:
 388			if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
 389				value.Type = Number
 390				value.Raw, value.Num = tonum(json[i:])
 391				value.Str = ""
 392			} else {
 393				continue
 394			}
 395		case '{', '[':
 396			value.Type = JSON
 397			value.Raw = squash(json[i:])
 398			value.Str, value.Num = "", 0
 399		case 'n':
 400			value.Type = Null
 401			value.Raw = tolit(json[i:])
 402			value.Str, value.Num = "", 0
 403		case 't':
 404			value.Type = True
 405			value.Raw = tolit(json[i:])
 406			value.Str, value.Num = "", 0
 407		case 'f':
 408			value.Type = False
 409			value.Raw = tolit(json[i:])
 410			value.Str, value.Num = "", 0
 411		case '"':
 412			value.Type = String
 413			value.Raw, value.Str = tostr(json[i:])
 414			value.Num = 0
 415		}
 416		value.Index = i + t.Index
 417
 418		i += len(value.Raw) - 1
 419
 420		if r.vc == '{' {
 421			if count%2 == 0 {
 422				key = value
 423			} else {
 424				if valueize {
 425					if _, ok := r.oi[key.Str]; !ok {
 426						r.oi[key.Str] = value.Value()
 427					}
 428				} else {
 429					if _, ok := r.o[key.Str]; !ok {
 430						r.o[key.Str] = value
 431					}
 432				}
 433			}
 434			count++
 435		} else {
 436			if valueize {
 437				r.ai = append(r.ai, value.Value())
 438			} else {
 439				r.a = append(r.a, value)
 440			}
 441		}
 442	}
 443end:
 444	if t.Indexes != nil {
 445		if len(t.Indexes) != len(r.a) {
 446			for i := 0; i < len(r.a); i++ {
 447				r.a[i].Index = 0
 448			}
 449		} else {
 450			for i := 0; i < len(r.a); i++ {
 451				r.a[i].Index = t.Indexes[i]
 452			}
 453		}
 454	}
 455	return
 456}
 457
 458// Parse parses the json and returns a result.
 459//
 460// This function expects that the json is well-formed, and does not validate.
 461// Invalid json will not panic, but it may return back unexpected results.
 462// If you are consuming JSON from an unpredictable source then you may want to
 463// use the Valid function first.
 464func Parse(json string) Result {
 465	var value Result
 466	i := 0
 467	for ; i < len(json); i++ {
 468		if json[i] == '{' || json[i] == '[' {
 469			value.Type = JSON
 470			value.Raw = json[i:] // just take the entire raw
 471			break
 472		}
 473		if json[i] <= ' ' {
 474			continue
 475		}
 476		switch json[i] {
 477		case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 478			'i', 'I', 'N':
 479			value.Type = Number
 480			value.Raw, value.Num = tonum(json[i:])
 481		case 'n':
 482			if i+1 < len(json) && json[i+1] != 'u' {
 483				// nan
 484				value.Type = Number
 485				value.Raw, value.Num = tonum(json[i:])
 486			} else {
 487				// null
 488				value.Type = Null
 489				value.Raw = tolit(json[i:])
 490			}
 491		case 't':
 492			value.Type = True
 493			value.Raw = tolit(json[i:])
 494		case 'f':
 495			value.Type = False
 496			value.Raw = tolit(json[i:])
 497		case '"':
 498			value.Type = String
 499			value.Raw, value.Str = tostr(json[i:])
 500		default:
 501			return Result{}
 502		}
 503		break
 504	}
 505	if value.Exists() {
 506		value.Index = i
 507	}
 508	return value
 509}
 510
 511// ParseBytes parses the json and returns a result.
 512// If working with bytes, this method preferred over Parse(string(data))
 513func ParseBytes(json []byte) Result {
 514	return Parse(string(json))
 515}
 516
 517func squash(json string) string {
 518	// expects that the lead character is a '[' or '{' or '(' or '"'
 519	// squash the value, ignoring all nested arrays and objects.
 520	var i, depth int
 521	if json[0] != '"' {
 522		i, depth = 1, 1
 523	}
 524	for ; i < len(json); i++ {
 525		if json[i] >= '"' && json[i] <= '}' {
 526			switch json[i] {
 527			case '"':
 528				i++
 529				s2 := i
 530				for ; i < len(json); i++ {
 531					if json[i] > '\\' {
 532						continue
 533					}
 534					if json[i] == '"' {
 535						// look for an escaped slash
 536						if json[i-1] == '\\' {
 537							n := 0
 538							for j := i - 2; j > s2-1; j-- {
 539								if json[j] != '\\' {
 540									break
 541								}
 542								n++
 543							}
 544							if n%2 == 0 {
 545								continue
 546							}
 547						}
 548						break
 549					}
 550				}
 551				if depth == 0 {
 552					if i >= len(json) {
 553						return json
 554					}
 555					return json[:i+1]
 556				}
 557			case '{', '[', '(':
 558				depth++
 559			case '}', ']', ')':
 560				depth--
 561				if depth == 0 {
 562					return json[:i+1]
 563				}
 564			}
 565		}
 566	}
 567	return json
 568}
 569
 570func tonum(json string) (raw string, num float64) {
 571	for i := 1; i < len(json); i++ {
 572		// less than dash might have valid characters
 573		if json[i] <= '-' {
 574			if json[i] <= ' ' || json[i] == ',' {
 575				// break on whitespace and comma
 576				raw = json[:i]
 577				num, _ = strconv.ParseFloat(raw, 64)
 578				return
 579			}
 580			// could be a '+' or '-'. let's assume so.
 581		} else if json[i] == ']' || json[i] == '}' {
 582			// break on ']' or '}'
 583			raw = json[:i]
 584			num, _ = strconv.ParseFloat(raw, 64)
 585			return
 586		}
 587	}
 588	raw = json
 589	num, _ = strconv.ParseFloat(raw, 64)
 590	return
 591}
 592
 593func tolit(json string) (raw string) {
 594	for i := 1; i < len(json); i++ {
 595		if json[i] < 'a' || json[i] > 'z' {
 596			return json[:i]
 597		}
 598	}
 599	return json
 600}
 601
 602func tostr(json string) (raw string, str string) {
 603	// expects that the lead character is a '"'
 604	for i := 1; i < len(json); i++ {
 605		if json[i] > '\\' {
 606			continue
 607		}
 608		if json[i] == '"' {
 609			return json[:i+1], json[1:i]
 610		}
 611		if json[i] == '\\' {
 612			i++
 613			for ; i < len(json); i++ {
 614				if json[i] > '\\' {
 615					continue
 616				}
 617				if json[i] == '"' {
 618					// look for an escaped slash
 619					if json[i-1] == '\\' {
 620						n := 0
 621						for j := i - 2; j > 0; j-- {
 622							if json[j] != '\\' {
 623								break
 624							}
 625							n++
 626						}
 627						if n%2 == 0 {
 628							continue
 629						}
 630					}
 631					return json[:i+1], unescape(json[1:i])
 632				}
 633			}
 634			var ret string
 635			if i+1 < len(json) {
 636				ret = json[:i+1]
 637			} else {
 638				ret = json[:i]
 639			}
 640			return ret, unescape(json[1:i])
 641		}
 642	}
 643	return json, json[1:]
 644}
 645
 646// Exists returns true if value exists.
 647//
 648//	 if gjson.Get(json, "name.last").Exists(){
 649//			println("value exists")
 650//	 }
 651func (t Result) Exists() bool {
 652	return t.Type != Null || len(t.Raw) != 0
 653}
 654
 655// Value returns one of these types:
 656//
 657//	bool, for JSON booleans
 658//	float64, for JSON numbers
 659//	Number, for JSON numbers
 660//	string, for JSON string literals
 661//	nil, for JSON null
 662//	map[string]interface{}, for JSON objects
 663//	[]interface{}, for JSON arrays
 664func (t Result) Value() interface{} {
 665	if t.Type == String {
 666		return t.Str
 667	}
 668	switch t.Type {
 669	default:
 670		return nil
 671	case False:
 672		return false
 673	case Number:
 674		return t.Num
 675	case JSON:
 676		r := t.arrayOrMap(0, true)
 677		if r.vc == '{' {
 678			return r.oi
 679		} else if r.vc == '[' {
 680			return r.ai
 681		}
 682		return nil
 683	case True:
 684		return true
 685	}
 686}
 687
 688func parseString(json string, i int) (int, string, bool, bool) {
 689	var s = i
 690	for ; i < len(json); i++ {
 691		if json[i] > '\\' {
 692			continue
 693		}
 694		if json[i] == '"' {
 695			return i + 1, json[s-1 : i+1], false, true
 696		}
 697		if json[i] == '\\' {
 698			i++
 699			for ; i < len(json); i++ {
 700				if json[i] > '\\' {
 701					continue
 702				}
 703				if json[i] == '"' {
 704					// look for an escaped slash
 705					if json[i-1] == '\\' {
 706						n := 0
 707						for j := i - 2; j > 0; j-- {
 708							if json[j] != '\\' {
 709								break
 710							}
 711							n++
 712						}
 713						if n%2 == 0 {
 714							continue
 715						}
 716					}
 717					return i + 1, json[s-1 : i+1], true, true
 718				}
 719			}
 720			break
 721		}
 722	}
 723	return i, json[s-1:], false, false
 724}
 725
 726func parseNumber(json string, i int) (int, string) {
 727	var s = i
 728	i++
 729	for ; i < len(json); i++ {
 730		if json[i] <= ' ' || json[i] == ',' || json[i] == ']' ||
 731			json[i] == '}' {
 732			return i, json[s:i]
 733		}
 734	}
 735	return i, json[s:]
 736}
 737
 738func parseLiteral(json string, i int) (int, string) {
 739	var s = i
 740	i++
 741	for ; i < len(json); i++ {
 742		if json[i] < 'a' || json[i] > 'z' {
 743			return i, json[s:i]
 744		}
 745	}
 746	return i, json[s:]
 747}
 748
 749type arrayPathResult struct {
 750	part    string
 751	path    string
 752	pipe    string
 753	piped   bool
 754	more    bool
 755	alogok  bool
 756	arrch   bool
 757	alogkey string
 758	query   struct {
 759		on    bool
 760		all   bool
 761		path  string
 762		op    string
 763		value string
 764	}
 765}
 766
 767func parseArrayPath(path string) (r arrayPathResult) {
 768	for i := 0; i < len(path); i++ {
 769		if path[i] == '|' {
 770			r.part = path[:i]
 771			r.pipe = path[i+1:]
 772			r.piped = true
 773			return
 774		}
 775		if path[i] == '.' {
 776			r.part = path[:i]
 777			if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1:]) {
 778				r.pipe = path[i+1:]
 779				r.piped = true
 780			} else {
 781				r.path = path[i+1:]
 782				r.more = true
 783			}
 784			return
 785		}
 786		if path[i] == '#' {
 787			r.arrch = true
 788			if i == 0 && len(path) > 1 {
 789				if path[1] == '.' {
 790					r.alogok = true
 791					r.alogkey = path[2:]
 792					r.path = path[:1]
 793				} else if path[1] == '[' || path[1] == '(' {
 794					// query
 795					r.query.on = true
 796					qpath, op, value, _, fi, vesc, ok :=
 797						parseQuery(path[i:])
 798					if !ok {
 799						// bad query, end now
 800						break
 801					}
 802					if len(value) >= 2 && value[0] == '"' &&
 803						value[len(value)-1] == '"' {
 804						value = value[1 : len(value)-1]
 805						if vesc {
 806							value = unescape(value)
 807						}
 808					}
 809					r.query.path = qpath
 810					r.query.op = op
 811					r.query.value = value
 812
 813					i = fi - 1
 814					if i+1 < len(path) && path[i+1] == '#' {
 815						r.query.all = true
 816					}
 817				}
 818			}
 819			continue
 820		}
 821	}
 822	r.part = path
 823	r.path = ""
 824	return
 825}
 826
 827// splitQuery takes a query and splits it into three parts:
 828//
 829//	path, op, middle, and right.
 830//
 831// So for this query:
 832//
 833//	#(first_name=="Murphy").last
 834//
 835// Becomes
 836//
 837//	first_name   # path
 838//	=="Murphy"   # middle
 839//	.last        # right
 840//
 841// Or,
 842//
 843//	#(service_roles.#(=="one")).cap
 844//
 845// Becomes
 846//
 847//	service_roles.#(=="one")   # path
 848//	                           # middle
 849//	.cap                       # right
 850func parseQuery(query string) (
 851	path, op, value, remain string, i int, vesc, ok bool,
 852) {
 853	if len(query) < 2 || query[0] != '#' ||
 854		(query[1] != '(' && query[1] != '[') {
 855		return "", "", "", "", i, false, false
 856	}
 857	i = 2
 858	j := 0 // start of value part
 859	depth := 1
 860	for ; i < len(query); i++ {
 861		if depth == 1 && j == 0 {
 862			switch query[i] {
 863			case '!', '=', '<', '>', '%':
 864				// start of the value part
 865				j = i
 866				continue
 867			}
 868		}
 869		if query[i] == '\\' {
 870			i++
 871		} else if query[i] == '[' || query[i] == '(' {
 872			depth++
 873		} else if query[i] == ']' || query[i] == ')' {
 874			depth--
 875			if depth == 0 {
 876				break
 877			}
 878		} else if query[i] == '"' {
 879			// inside selector string, balance quotes
 880			i++
 881			for ; i < len(query); i++ {
 882				if query[i] == '\\' {
 883					vesc = true
 884					i++
 885				} else if query[i] == '"' {
 886					break
 887				}
 888			}
 889		}
 890	}
 891	if depth > 0 {
 892		return "", "", "", "", i, false, false
 893	}
 894	if j > 0 {
 895		path = trim(query[2:j])
 896		value = trim(query[j:i])
 897		remain = query[i+1:]
 898		// parse the compare op from the value
 899		var opsz int
 900		switch {
 901		case len(value) == 1:
 902			opsz = 1
 903		case value[0] == '!' && value[1] == '=':
 904			opsz = 2
 905		case value[0] == '!' && value[1] == '%':
 906			opsz = 2
 907		case value[0] == '<' && value[1] == '=':
 908			opsz = 2
 909		case value[0] == '>' && value[1] == '=':
 910			opsz = 2
 911		case value[0] == '=' && value[1] == '=':
 912			value = value[1:]
 913			opsz = 1
 914		case value[0] == '<':
 915			opsz = 1
 916		case value[0] == '>':
 917			opsz = 1
 918		case value[0] == '=':
 919			opsz = 1
 920		case value[0] == '%':
 921			opsz = 1
 922		}
 923		op = value[:opsz]
 924		value = trim(value[opsz:])
 925	} else {
 926		path = trim(query[2:i])
 927		remain = query[i+1:]
 928	}
 929	return path, op, value, remain, i + 1, vesc, true
 930}
 931
 932func trim(s string) string {
 933left:
 934	if len(s) > 0 && s[0] <= ' ' {
 935		s = s[1:]
 936		goto left
 937	}
 938right:
 939	if len(s) > 0 && s[len(s)-1] <= ' ' {
 940		s = s[:len(s)-1]
 941		goto right
 942	}
 943	return s
 944}
 945
 946// peek at the next byte and see if it's a '@', '[', or '{'.
 947func isDotPiperChar(s string) bool {
 948	if DisableModifiers {
 949		return false
 950	}
 951	c := s[0]
 952	if c == '@' {
 953		// check that the next component is *not* a modifier.
 954		i := 1
 955		for ; i < len(s); i++ {
 956			if s[i] == '.' || s[i] == '|' || s[i] == ':' {
 957				break
 958			}
 959		}
 960		_, ok := modifiers[s[1:i]]
 961		return ok
 962	}
 963	return c == '[' || c == '{'
 964}
 965
 966type objectPathResult struct {
 967	part  string
 968	path  string
 969	pipe  string
 970	piped bool
 971	wild  bool
 972	more  bool
 973}
 974
 975func parseObjectPath(path string) (r objectPathResult) {
 976	for i := 0; i < len(path); i++ {
 977		if path[i] == '|' {
 978			r.part = path[:i]
 979			r.pipe = path[i+1:]
 980			r.piped = true
 981			return
 982		}
 983		if path[i] == '.' {
 984			r.part = path[:i]
 985			if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
 986				r.pipe = path[i+1:]
 987				r.piped = true
 988			} else {
 989				r.path = path[i+1:]
 990				r.more = true
 991			}
 992			return
 993		}
 994		if path[i] == '*' || path[i] == '?' {
 995			r.wild = true
 996			continue
 997		}
 998		if path[i] == '\\' {
 999			// go into escape mode. this is a slower path that
1000			// strips off the escape character from the part.
1001			epart := []byte(path[:i])
1002			i++
1003			if i < len(path) {
1004				epart = append(epart, path[i])
1005				i++
1006				for ; i < len(path); i++ {
1007					if path[i] == '\\' {
1008						i++
1009						if i < len(path) {
1010							epart = append(epart, path[i])
1011						}
1012						continue
1013					} else if path[i] == '.' {
1014						r.part = string(epart)
1015						if i < len(path)-1 && isDotPiperChar(path[i+1:]) {
1016							r.pipe = path[i+1:]
1017							r.piped = true
1018						} else {
1019							r.path = path[i+1:]
1020							r.more = true
1021						}
1022						return
1023					} else if path[i] == '|' {
1024						r.part = string(epart)
1025						r.pipe = path[i+1:]
1026						r.piped = true
1027						return
1028					} else if path[i] == '*' || path[i] == '?' {
1029						r.wild = true
1030					}
1031					epart = append(epart, path[i])
1032				}
1033			}
1034			// append the last part
1035			r.part = string(epart)
1036			return
1037		}
1038	}
1039	r.part = path
1040	return
1041}
1042
1043var vchars = [256]byte{
1044	'"': 2, '{': 3, '(': 3, '[': 3, '}': 1, ')': 1, ']': 1,
1045}
1046
1047func parseSquash(json string, i int) (int, string) {
1048	// expects that the lead character is a '[' or '{' or '('
1049	// squash the value, ignoring all nested arrays and objects.
1050	// the first '[' or '{' or '(' has already been read
1051	s := i
1052	i++
1053	depth := 1
1054	var c byte
1055	for i < len(json) {
1056		for i < len(json)-8 {
1057			jslice := json[i : i+8]
1058			c = vchars[jslice[0]]
1059			if c != 0 {
1060				i += 0
1061				goto token
1062			}
1063			c = vchars[jslice[1]]
1064			if c != 0 {
1065				i += 1
1066				goto token
1067			}
1068			c = vchars[jslice[2]]
1069			if c != 0 {
1070				i += 2
1071				goto token
1072			}
1073			c = vchars[jslice[3]]
1074			if c != 0 {
1075				i += 3
1076				goto token
1077			}
1078			c = vchars[jslice[4]]
1079			if c != 0 {
1080				i += 4
1081				goto token
1082			}
1083			c = vchars[jslice[5]]
1084			if c != 0 {
1085				i += 5
1086				goto token
1087			}
1088			c = vchars[jslice[6]]
1089			if c != 0 {
1090				i += 6
1091				goto token
1092			}
1093			c = vchars[jslice[7]]
1094			if c != 0 {
1095				i += 7
1096				goto token
1097			}
1098			i += 8
1099		}
1100		c = vchars[json[i]]
1101		if c == 0 {
1102			i++
1103			continue
1104		}
1105	token:
1106		if c == 2 {
1107			// '"' string
1108			i++
1109			s2 := i
1110		nextquote:
1111			for i < len(json)-8 {
1112				jslice := json[i : i+8]
1113				if jslice[0] == '"' {
1114					i += 0
1115					goto strchkesc
1116				}
1117				if jslice[1] == '"' {
1118					i += 1
1119					goto strchkesc
1120				}
1121				if jslice[2] == '"' {
1122					i += 2
1123					goto strchkesc
1124				}
1125				if jslice[3] == '"' {
1126					i += 3
1127					goto strchkesc
1128				}
1129				if jslice[4] == '"' {
1130					i += 4
1131					goto strchkesc
1132				}
1133				if jslice[5] == '"' {
1134					i += 5
1135					goto strchkesc
1136				}
1137				if jslice[6] == '"' {
1138					i += 6
1139					goto strchkesc
1140				}
1141				if jslice[7] == '"' {
1142					i += 7
1143					goto strchkesc
1144				}
1145				i += 8
1146			}
1147			goto strchkstd
1148		strchkesc:
1149			if json[i-1] != '\\' {
1150				i++
1151				continue
1152			}
1153		strchkstd:
1154			for i < len(json) {
1155				if json[i] > '\\' || json[i] != '"' {
1156					i++
1157					continue
1158				}
1159				// look for an escaped slash
1160				if json[i-1] == '\\' {
1161					n := 0
1162					for j := i - 2; j > s2-1; j-- {
1163						if json[j] != '\\' {
1164							break
1165						}
1166						n++
1167					}
1168					if n%2 == 0 {
1169						i++
1170						goto nextquote
1171					}
1172				}
1173				break
1174			}
1175		} else {
1176			// '{', '[', '(', '}', ']', ')'
1177			// open close tokens
1178			depth += int(c) - 2
1179			if depth == 0 {
1180				i++
1181				return i, json[s:i]
1182			}
1183		}
1184		i++
1185	}
1186	return i, json[s:]
1187}
1188
1189func parseObject(c *parseContext, i int, path string) (int, bool) {
1190	var pmatch, kesc, vesc, ok, hit bool
1191	var key, val string
1192	rp := parseObjectPath(path)
1193	if !rp.more && rp.piped {
1194		c.pipe = rp.pipe
1195		c.piped = true
1196	}
1197	for i < len(c.json) {
1198		for ; i < len(c.json); i++ {
1199			if c.json[i] == '"' {
1200				// parse_key_string
1201				// this is slightly different from getting s string value
1202				// because we don't need the outer quotes.
1203				i++
1204				var s = i
1205				for ; i < len(c.json); i++ {
1206					if c.json[i] > '\\' {
1207						continue
1208					}
1209					if c.json[i] == '"' {
1210						i, key, kesc, ok = i+1, c.json[s:i], false, true
1211						goto parse_key_string_done
1212					}
1213					if c.json[i] == '\\' {
1214						i++
1215						for ; i < len(c.json); i++ {
1216							if c.json[i] > '\\' {
1217								continue
1218							}
1219							if c.json[i] == '"' {
1220								// look for an escaped slash
1221								if c.json[i-1] == '\\' {
1222									n := 0
1223									for j := i - 2; j > 0; j-- {
1224										if c.json[j] != '\\' {
1225											break
1226										}
1227										n++
1228									}
1229									if n%2 == 0 {
1230										continue
1231									}
1232								}
1233								i, key, kesc, ok = i+1, c.json[s:i], true, true
1234								goto parse_key_string_done
1235							}
1236						}
1237						break
1238					}
1239				}
1240				key, kesc, ok = c.json[s:], false, false
1241			parse_key_string_done:
1242				break
1243			}
1244			if c.json[i] == '}' {
1245				return i + 1, false
1246			}
1247		}
1248		if !ok {
1249			return i, false
1250		}
1251		if rp.wild {
1252			if kesc {
1253				pmatch = matchLimit(unescape(key), rp.part)
1254			} else {
1255				pmatch = matchLimit(key, rp.part)
1256			}
1257		} else {
1258			if kesc {
1259				pmatch = rp.part == unescape(key)
1260			} else {
1261				pmatch = rp.part == key
1262			}
1263		}
1264		hit = pmatch && !rp.more
1265		for ; i < len(c.json); i++ {
1266			var num bool
1267			switch c.json[i] {
1268			default:
1269				continue
1270			case '"':
1271				i++
1272				i, val, vesc, ok = parseString(c.json, i)
1273				if !ok {
1274					return i, false
1275				}
1276				if hit {
1277					if vesc {
1278						c.value.Str = unescape(val[1 : len(val)-1])
1279					} else {
1280						c.value.Str = val[1 : len(val)-1]
1281					}
1282					c.value.Raw = val
1283					c.value.Type = String
1284					return i, true
1285				}
1286			case '{':
1287				if pmatch && !hit {
1288					i, hit = parseObject(c, i+1, rp.path)
1289					if hit {
1290						return i, true
1291					}
1292				} else {
1293					i, val = parseSquash(c.json, i)
1294					if hit {
1295						c.value.Raw = val
1296						c.value.Type = JSON
1297						return i, true
1298					}
1299				}
1300			case '[':
1301				if pmatch && !hit {
1302					i, hit = parseArray(c, i+1, rp.path)
1303					if hit {
1304						return i, true
1305					}
1306				} else {
1307					i, val = parseSquash(c.json, i)
1308					if hit {
1309						c.value.Raw = val
1310						c.value.Type = JSON
1311						return i, true
1312					}
1313				}
1314			case 'n':
1315				if i+1 < len(c.json) && c.json[i+1] != 'u' {
1316					num = true
1317					break
1318				}
1319				fallthrough
1320			case 't', 'f':
1321				vc := c.json[i]
1322				i, val = parseLiteral(c.json, i)
1323				if hit {
1324					c.value.Raw = val
1325					switch vc {
1326					case 't':
1327						c.value.Type = True
1328					case 'f':
1329						c.value.Type = False
1330					}
1331					return i, true
1332				}
1333			case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1334				'i', 'I', 'N':
1335				num = true
1336			}
1337			if num {
1338				i, val = parseNumber(c.json, i)
1339				if hit {
1340					c.value.Raw = val
1341					c.value.Type = Number
1342					c.value.Num, _ = strconv.ParseFloat(val, 64)
1343					return i, true
1344				}
1345			}
1346			break
1347		}
1348	}
1349	return i, false
1350}
1351
1352// matchLimit will limit the complexity of the match operation to avoid ReDos
1353// attacks from arbitrary inputs.
1354// See the github.com/tidwall/match.MatchLimit function for more information.
1355func matchLimit(str, pattern string) bool {
1356	matched, _ := match.MatchLimit(str, pattern, 10000)
1357	return matched
1358}
1359
1360func falseish(t Result) bool {
1361	switch t.Type {
1362	case Null:
1363		return true
1364	case False:
1365		return true
1366	case String:
1367		b, err := strconv.ParseBool(strings.ToLower(t.Str))
1368		if err != nil {
1369			return false
1370		}
1371		return !b
1372	case Number:
1373		return t.Num == 0
1374	default:
1375		return false
1376	}
1377}
1378
1379func trueish(t Result) bool {
1380	switch t.Type {
1381	case True:
1382		return true
1383	case String:
1384		b, err := strconv.ParseBool(strings.ToLower(t.Str))
1385		if err != nil {
1386			return false
1387		}
1388		return b
1389	case Number:
1390		return t.Num != 0
1391	default:
1392		return false
1393	}
1394}
1395
1396func nullish(t Result) bool {
1397	return t.Type == Null
1398}
1399
1400func queryMatches(rp *arrayPathResult, value Result) bool {
1401	rpv := rp.query.value
1402	if len(rpv) > 0 {
1403		if rpv[0] == '~' {
1404			// convert to bool
1405			rpv = rpv[1:]
1406			var ish, ok bool
1407			switch rpv {
1408			case "*":
1409				ish, ok = value.Exists(), true
1410			case "null":
1411				ish, ok = nullish(value), true
1412			case "true":
1413				ish, ok = trueish(value), true
1414			case "false":
1415				ish, ok = falseish(value), true
1416			}
1417			if ok {
1418				rpv = "true"
1419				if ish {
1420					value = Result{Type: True}
1421				} else {
1422					value = Result{Type: False}
1423				}
1424			} else {
1425				rpv = ""
1426				value = Result{}
1427			}
1428		}
1429	}
1430	if !value.Exists() {
1431		return false
1432	}
1433	if rp.query.op == "" {
1434		// the query is only looking for existence, such as:
1435		//   friends.#(name)
1436		// which makes sure that the array "friends" has an element of
1437		// "name" that exists
1438		return true
1439	}
1440	switch value.Type {
1441	case String:
1442		switch rp.query.op {
1443		case "=":
1444			return value.Str == rpv
1445		case "!=":
1446			return value.Str != rpv
1447		case "<":
1448			return value.Str < rpv
1449		case "<=":
1450			return value.Str <= rpv
1451		case ">":
1452			return value.Str > rpv
1453		case ">=":
1454			return value.Str >= rpv
1455		case "%":
1456			return matchLimit(value.Str, rpv)
1457		case "!%":
1458			return !matchLimit(value.Str, rpv)
1459		}
1460	case Number:
1461		rpvn, _ := strconv.ParseFloat(rpv, 64)
1462		switch rp.query.op {
1463		case "=":
1464			return value.Num == rpvn
1465		case "!=":
1466			return value.Num != rpvn
1467		case "<":
1468			return value.Num < rpvn
1469		case "<=":
1470			return value.Num <= rpvn
1471		case ">":
1472			return value.Num > rpvn
1473		case ">=":
1474			return value.Num >= rpvn
1475		}
1476	case True:
1477		switch rp.query.op {
1478		case "=":
1479			return rpv == "true"
1480		case "!=":
1481			return rpv != "true"
1482		case ">":
1483			return rpv == "false"
1484		case ">=":
1485			return true
1486		}
1487	case False:
1488		switch rp.query.op {
1489		case "=":
1490			return rpv == "false"
1491		case "!=":
1492			return rpv != "false"
1493		case "<":
1494			return rpv == "true"
1495		case "<=":
1496			return true
1497		}
1498	}
1499	return false
1500}
1501func parseArray(c *parseContext, i int, path string) (int, bool) {
1502	var pmatch, vesc, ok, hit bool
1503	var val string
1504	var h int
1505	var alog []int
1506	var partidx int
1507	var multires []byte
1508	var queryIndexes []int
1509	rp := parseArrayPath(path)
1510	if !rp.arrch {
1511		n, ok := parseUint(rp.part)
1512		if !ok {
1513			partidx = -1
1514		} else {
1515			partidx = int(n)
1516		}
1517	}
1518	if !rp.more && rp.piped {
1519		c.pipe = rp.pipe
1520		c.piped = true
1521	}
1522
1523	procQuery := func(qval Result) bool {
1524		if rp.query.all {
1525			if len(multires) == 0 {
1526				multires = append(multires, '[')
1527			}
1528		}
1529		var tmp parseContext
1530		tmp.value = qval
1531		fillIndex(c.json, &tmp)
1532		parentIndex := tmp.value.Index
1533		var res Result
1534		if qval.Type == JSON {
1535			res = qval.Get(rp.query.path)
1536		} else {
1537			if rp.query.path != "" {
1538				return false
1539			}
1540			res = qval
1541		}
1542		if queryMatches(&rp, res) {
1543			if rp.more {
1544				left, right, ok := splitPossiblePipe(rp.path)
1545				if ok {
1546					rp.path = left
1547					c.pipe = right
1548					c.piped = true
1549				}
1550				res = qval.Get(rp.path)
1551			} else {
1552				res = qval
1553			}
1554			if rp.query.all {
1555				raw := res.Raw
1556				if len(raw) == 0 {
1557					raw = res.String()
1558				}
1559				if raw != "" {
1560					if len(multires) > 1 {
1561						multires = append(multires, ',')
1562					}
1563					multires = append(multires, raw...)
1564					queryIndexes = append(queryIndexes, res.Index+parentIndex)
1565				}
1566			} else {
1567				c.value = res
1568				return true
1569			}
1570		}
1571		return false
1572	}
1573	for i < len(c.json)+1 {
1574		if !rp.arrch {
1575			pmatch = partidx == h
1576			hit = pmatch && !rp.more
1577		}
1578		h++
1579		if rp.alogok {
1580			alog = append(alog, i)
1581		}
1582		for ; ; i++ {
1583			var ch byte
1584			if i > len(c.json) {
1585				break
1586			} else if i == len(c.json) {
1587				ch = ']'
1588			} else {
1589				ch = c.json[i]
1590			}
1591			var num bool
1592			switch ch {
1593			default:
1594				continue
1595			case '"':
1596				i++
1597				i, val, vesc, ok = parseString(c.json, i)
1598				if !ok {
1599					return i, false
1600				}
1601				if rp.query.on {
1602					var qval Result
1603					if vesc {
1604						qval.Str = unescape(val[1 : len(val)-1])
1605					} else {
1606						qval.Str = val[1 : len(val)-1]
1607					}
1608					qval.Raw = val
1609					qval.Type = String
1610					if procQuery(qval) {
1611						return i, true
1612					}
1613				} else if hit {
1614					if rp.alogok {
1615						break
1616					}
1617					if vesc {
1618						c.value.Str = unescape(val[1 : len(val)-1])
1619					} else {
1620						c.value.Str = val[1 : len(val)-1]
1621					}
1622					c.value.Raw = val
1623					c.value.Type = String
1624					return i, true
1625				}
1626			case '{':
1627				if pmatch && !hit {
1628					i, hit = parseObject(c, i+1, rp.path)
1629					if hit {
1630						if rp.alogok {
1631							break
1632						}
1633						return i, true
1634					}
1635				} else {
1636					i, val = parseSquash(c.json, i)
1637					if rp.query.on {
1638						if procQuery(Result{Raw: val, Type: JSON}) {
1639							return i, true
1640						}
1641					} else if hit {
1642						if rp.alogok {
1643							break
1644						}
1645						c.value.Raw = val
1646						c.value.Type = JSON
1647						return i, true
1648					}
1649				}
1650			case '[':
1651				if pmatch && !hit {
1652					i, hit = parseArray(c, i+1, rp.path)
1653					if hit {
1654						if rp.alogok {
1655							break
1656						}
1657						return i, true
1658					}
1659				} else {
1660					i, val = parseSquash(c.json, i)
1661					if rp.query.on {
1662						if procQuery(Result{Raw: val, Type: JSON}) {
1663							return i, true
1664						}
1665					} else if hit {
1666						if rp.alogok {
1667							break
1668						}
1669						c.value.Raw = val
1670						c.value.Type = JSON
1671						return i, true
1672					}
1673				}
1674			case 'n':
1675				if i+1 < len(c.json) && c.json[i+1] != 'u' {
1676					num = true
1677					break
1678				}
1679				fallthrough
1680			case 't', 'f':
1681				vc := c.json[i]
1682				i, val = parseLiteral(c.json, i)
1683				if rp.query.on {
1684					var qval Result
1685					qval.Raw = val
1686					switch vc {
1687					case 't':
1688						qval.Type = True
1689					case 'f':
1690						qval.Type = False
1691					}
1692					if procQuery(qval) {
1693						return i, true
1694					}
1695				} else if hit {
1696					if rp.alogok {
1697						break
1698					}
1699					c.value.Raw = val
1700					switch vc {
1701					case 't':
1702						c.value.Type = True
1703					case 'f':
1704						c.value.Type = False
1705					}
1706					return i, true
1707				}
1708			case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
1709				'i', 'I', 'N':
1710				num = true
1711			case ']':
1712				if rp.arrch && rp.part == "#" {
1713					if rp.alogok {
1714						left, right, ok := splitPossiblePipe(rp.alogkey)
1715						if ok {
1716							rp.alogkey = left
1717							c.pipe = right
1718							c.piped = true
1719						}
1720						var indexes = make([]int, 0, 64)
1721						var jsons = make([]byte, 0, 64)
1722						jsons = append(jsons, '[')
1723						for j, k := 0, 0; j < len(alog); j++ {
1724							idx := alog[j]
1725							for idx < len(c.json) {
1726								switch c.json[idx] {
1727								case ' ', '\t', '\r', '\n':
1728									idx++
1729									continue
1730								}
1731								break
1732							}
1733							if idx < len(c.json) && c.json[idx] != ']' {
1734								_, res, ok := parseAny(c.json, idx, true)
1735								if ok {
1736									res := res.Get(rp.alogkey)
1737									if res.Exists() {
1738										if k > 0 {
1739											jsons = append(jsons, ',')
1740										}
1741										raw := res.Raw
1742										if len(raw) == 0 {
1743											raw = res.String()
1744										}
1745										jsons = append(jsons, []byte(raw)...)
1746										indexes = append(indexes, res.Index)
1747										k++
1748									}
1749								}
1750							}
1751						}
1752						jsons = append(jsons, ']')
1753						c.value.Type = JSON
1754						c.value.Raw = string(jsons)
1755						c.value.Indexes = indexes
1756						return i + 1, true
1757					}
1758					if rp.alogok {
1759						break
1760					}
1761
1762					c.value.Type = Number
1763					c.value.Num = float64(h - 1)
1764					c.value.Raw = strconv.Itoa(h - 1)
1765					c.calcd = true
1766					return i + 1, true
1767				}
1768				if !c.value.Exists() {
1769					if len(multires) > 0 {
1770						c.value = Result{
1771							Raw:     string(append(multires, ']')),
1772							Type:    JSON,
1773							Indexes: queryIndexes,
1774						}
1775					} else if rp.query.all {
1776						c.value = Result{
1777							Raw:  "[]",
1778							Type: JSON,
1779						}
1780					}
1781				}
1782				return i + 1, false
1783			}
1784			if num {
1785				i, val = parseNumber(c.json, i)
1786				if rp.query.on {
1787					var qval Result
1788					qval.Raw = val
1789					qval.Type = Number
1790					qval.Num, _ = strconv.ParseFloat(val, 64)
1791					if procQuery(qval) {
1792						return i, true
1793					}
1794				} else if hit {
1795					if rp.alogok {
1796						break
1797					}
1798					c.value.Raw = val
1799					c.value.Type = Number
1800					c.value.Num, _ = strconv.ParseFloat(val, 64)
1801					return i, true
1802				}
1803			}
1804			break
1805		}
1806	}
1807	return i, false
1808}
1809
1810func splitPossiblePipe(path string) (left, right string, ok bool) {
1811	// take a quick peek for the pipe character. If found we'll split the piped
1812	// part of the path into the c.pipe field and shorten the rp.
1813	var possible bool
1814	for i := 0; i < len(path); i++ {
1815		if path[i] == '|' {
1816			possible = true
1817			break
1818		}
1819	}
1820	if !possible {
1821		return
1822	}
1823
1824	if len(path) > 0 && path[0] == '{' {
1825		squashed := squash(path[1:])
1826		if len(squashed) < len(path)-1 {
1827			squashed = path[:len(squashed)+1]
1828			remain := path[len(squashed):]
1829			if remain[0] == '|' {
1830				return squashed, remain[1:], true
1831			}
1832		}
1833		return
1834	}
1835
1836	// split the left and right side of the path with the pipe character as
1837	// the delimiter. This is a little tricky because we'll need to basically
1838	// parse the entire path.
1839	for i := 0; i < len(path); i++ {
1840		if path[i] == '\\' {
1841			i++
1842		} else if path[i] == '.' {
1843			if i == len(path)-1 {
1844				return
1845			}
1846			if path[i+1] == '#' {
1847				i += 2
1848				if i == len(path) {
1849					return
1850				}
1851				if path[i] == '[' || path[i] == '(' {
1852					var start, end byte
1853					if path[i] == '[' {
1854						start, end = '[', ']'
1855					} else {
1856						start, end = '(', ')'
1857					}
1858					// inside selector, balance brackets
1859					i++
1860					depth := 1
1861					for ; i < len(path); i++ {
1862						if path[i] == '\\' {
1863							i++
1864						} else if path[i] == start {
1865							depth++
1866						} else if path[i] == end {
1867							depth--
1868							if depth == 0 {
1869								break
1870							}
1871						} else if path[i] == '"' {
1872							// inside selector string, balance quotes
1873							i++
1874							for ; i < len(path); i++ {
1875								if path[i] == '\\' {
1876									i++
1877								} else if path[i] == '"' {
1878									break
1879								}
1880							}
1881						}
1882					}
1883				}
1884			}
1885		} else if path[i] == '|' {
1886			return path[:i], path[i+1:], true
1887		}
1888	}
1889	return
1890}
1891
1892// ForEachLine iterates through lines of JSON as specified by the JSON Lines
1893// format (http://jsonlines.org/).
1894// Each line is returned as a GJSON Result.
1895func ForEachLine(json string, iterator func(line Result) bool) {
1896	var res Result
1897	var i int
1898	for {
1899		i, res, _ = parseAny(json, i, true)
1900		if !res.Exists() {
1901			break
1902		}
1903		if !iterator(res) {
1904			return
1905		}
1906	}
1907}
1908
1909type subSelector struct {
1910	name string
1911	path string
1912}
1913
1914// parseSubSelectors returns the subselectors belonging to a '[path1,path2]' or
1915// '{"field1":path1,"field2":path2}' type subSelection. It's expected that the
1916// first character in path is either '[' or '{', and has already been checked
1917// prior to calling this function.
1918func parseSubSelectors(path string) (sels []subSelector, out string, ok bool) {
1919	modifier := 0
1920	depth := 1
1921	colon := 0
1922	start := 1
1923	i := 1
1924	pushSel := func() {
1925		var sel subSelector
1926		if colon == 0 {
1927			sel.path = path[start:i]
1928		} else {
1929			sel.name = path[start:colon]
1930			sel.path = path[colon+1 : i]
1931		}
1932		sels = append(sels, sel)
1933		colon = 0
1934		modifier = 0
1935		start = i + 1
1936	}
1937	for ; i < len(path); i++ {
1938		switch path[i] {
1939		case '\\':
1940			i++
1941		case '@':
1942			if modifier == 0 && i > 0 && (path[i-1] == '.' || path[i-1] == '|') {
1943				modifier = i
1944			}
1945		case ':':
1946			if modifier == 0 && colon == 0 && depth == 1 {
1947				colon = i
1948			}
1949		case ',':
1950			if depth == 1 {
1951				pushSel()
1952			}
1953		case '"':
1954			i++
1955		loop:
1956			for ; i < len(path); i++ {
1957				switch path[i] {
1958				case '\\':
1959					i++
1960				case '"':
1961					break loop
1962				}
1963			}
1964		case '[', '(', '{':
1965			depth++
1966		case ']', ')', '}':
1967			depth--
1968			if depth == 0 {
1969				pushSel()
1970				path = path[i+1:]
1971				return sels, path, true
1972			}
1973		}
1974	}
1975	return
1976}
1977
1978// nameOfLast returns the name of the last component
1979func nameOfLast(path string) string {
1980	for i := len(path) - 1; i >= 0; i-- {
1981		if path[i] == '|' || path[i] == '.' {
1982			if i > 0 {
1983				if path[i-1] == '\\' {
1984					continue
1985				}
1986			}
1987			return path[i+1:]
1988		}
1989	}
1990	return path
1991}
1992
1993func isSimpleName(component string) bool {
1994	for i := 0; i < len(component); i++ {
1995		if component[i] < ' ' {
1996			return false
1997		}
1998		switch component[i] {
1999		case '[', ']', '{', '}', '(', ')', '#', '|', '!':
2000			return false
2001		}
2002	}
2003	return true
2004}
2005
2006var hexchars = [...]byte{
2007	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2008	'a', 'b', 'c', 'd', 'e', 'f',
2009}
2010
2011func appendHex16(dst []byte, x uint16) []byte {
2012	return append(dst,
2013		hexchars[x>>12&0xF], hexchars[x>>8&0xF],
2014		hexchars[x>>4&0xF], hexchars[x>>0&0xF],
2015	)
2016}
2017
2018// DisableEscapeHTML will disable the automatic escaping of certain
2019// "problamatic" HTML characters when encoding to JSON.
2020// These character include '>', '<' and '&', which get escaped to \u003e,
2021// \u0026, and \u003c respectively.
2022//
2023// This is a global flag and will affect all further gjson operations.
2024// Ideally, if used, it should be set one time before other gjson functions
2025// are called.
2026var DisableEscapeHTML = false
2027
2028// AppendJSONString is a convenience function that converts the provided string
2029// to a valid JSON string and appends it to dst.
2030func AppendJSONString(dst []byte, s string) []byte {
2031	dst = append(dst, make([]byte, len(s)+2)...)
2032	dst = append(dst[:len(dst)-len(s)-2], '"')
2033	for i := 0; i < len(s); i++ {
2034		if s[i] < ' ' {
2035			dst = append(dst, '\\')
2036			switch s[i] {
2037			case '\b':
2038				dst = append(dst, 'b')
2039			case '\f':
2040				dst = append(dst, 'f')
2041			case '\n':
2042				dst = append(dst, 'n')
2043			case '\r':
2044				dst = append(dst, 'r')
2045			case '\t':
2046				dst = append(dst, 't')
2047			default:
2048				dst = append(dst, 'u')
2049				dst = appendHex16(dst, uint16(s[i]))
2050			}
2051		} else if !DisableEscapeHTML &&
2052			(s[i] == '>' || s[i] == '<' || s[i] == '&') {
2053			dst = append(dst, '\\', 'u')
2054			dst = appendHex16(dst, uint16(s[i]))
2055		} else if s[i] == '\\' {
2056			dst = append(dst, '\\', '\\')
2057		} else if s[i] == '"' {
2058			dst = append(dst, '\\', '"')
2059		} else if s[i] > 127 {
2060			// read utf8 character
2061			r, n := utf8.DecodeRuneInString(s[i:])
2062			if n == 0 {
2063				break
2064			}
2065			if r == utf8.RuneError && n == 1 {
2066				dst = append(dst, `\ufffd`...)
2067			} else if r == '\u2028' || r == '\u2029' {
2068				dst = append(dst, `\u202`...)
2069				dst = append(dst, hexchars[r&0xF])
2070			} else {
2071				dst = append(dst, s[i:i+n]...)
2072			}
2073			i = i + n - 1
2074		} else {
2075			dst = append(dst, s[i])
2076		}
2077	}
2078	return append(dst, '"')
2079}
2080
2081type parseContext struct {
2082	json  string
2083	value Result
2084	pipe  string
2085	piped bool
2086	calcd bool
2087	lines bool
2088}
2089
2090// Get searches json for the specified path.
2091// A path is in dot syntax, such as "name.last" or "age".
2092// When the value is found it's returned immediately.
2093//
2094// A path is a series of keys separated by a dot.
2095// A key may contain special wildcard characters '*' and '?'.
2096// To access an array value use the index as the key.
2097// To get the number of elements in an array or to access a child path, use
2098// the '#' character.
2099// The dot and wildcard character can be escaped with '\'.
2100//
2101//	{
2102//	  "name": {"first": "Tom", "last": "Anderson"},
2103//	  "age":37,
2104//	  "children": ["Sara","Alex","Jack"],
2105//	  "friends": [
2106//	    {"first": "James", "last": "Murphy"},
2107//	    {"first": "Roger", "last": "Craig"}
2108//	  ]
2109//	}
2110//	"name.last"          >> "Anderson"
2111//	"age"                >> 37
2112//	"children"           >> ["Sara","Alex","Jack"]
2113//	"children.#"         >> 3
2114//	"children.1"         >> "Alex"
2115//	"child*.2"           >> "Jack"
2116//	"c?ildren.0"         >> "Sara"
2117//	"friends.#.first"    >> ["James","Roger"]
2118//
2119// This function expects that the json is well-formed, and does not validate.
2120// Invalid json will not panic, but it may return back unexpected results.
2121// If you are consuming JSON from an unpredictable source then you may want to
2122// use the Valid function first.
2123func Get(json, path string) Result {
2124	if len(path) > 1 {
2125		if (path[0] == '@' && !DisableModifiers) || path[0] == '!' {
2126			// possible modifier
2127			var ok bool
2128			var npath string
2129			var rjson string
2130			if path[0] == '@' && !DisableModifiers {
2131				npath, rjson, ok = execModifier(json, path)
2132			} else if path[0] == '!' {
2133				npath, rjson, ok = execStatic(json, path)
2134			}
2135			if ok {
2136				path = npath
2137				if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
2138					res := Get(rjson, path[1:])
2139					res.Index = 0
2140					res.Indexes = nil
2141					return res
2142				}
2143				return Parse(rjson)
2144			}
2145		}
2146		if path[0] == '[' || path[0] == '{' {
2147			// using a subselector path
2148			kind := path[0]
2149			var ok bool
2150			var subs []subSelector
2151			subs, path, ok = parseSubSelectors(path)
2152			if ok {
2153				if len(path) == 0 || (path[0] == '|' || path[0] == '.') {
2154					var b []byte
2155					b = append(b, kind)
2156					var i int
2157					for _, sub := range subs {
2158						res := Get(json, sub.path)
2159						if res.Exists() {
2160							if i > 0 {
2161								b = append(b, ',')
2162							}
2163							if kind == '{' {
2164								if len(sub.name) > 0 {
2165									if sub.name[0] == '"' && Valid(sub.name) {
2166										b = append(b, sub.name...)
2167									} else {
2168										b = AppendJSONString(b, sub.name)
2169									}
2170								} else {
2171									last := nameOfLast(sub.path)
2172									if isSimpleName(last) {
2173										b = AppendJSONString(b, last)
2174									} else {
2175										b = AppendJSONString(b, "_")
2176									}
2177								}
2178								b = append(b, ':')
2179							}
2180							var raw string
2181							if len(res.Raw) == 0 {
2182								raw = res.String()
2183								if len(raw) == 0 {
2184									raw = "null"
2185								}
2186							} else {
2187								raw = res.Raw
2188							}
2189							b = append(b, raw...)
2190							i++
2191						}
2192					}
2193					b = append(b, kind+2)
2194					var res Result
2195					res.Raw = string(b)
2196					res.Type = JSON
2197					if len(path) > 0 {
2198						res = res.Get(path[1:])
2199					}
2200					res.Index = 0
2201					return res
2202				}
2203			}
2204		}
2205	}
2206	var i int
2207	var c = &parseContext{json: json}
2208	if len(path) >= 2 && path[0] == '.' && path[1] == '.' {
2209		c.lines = true
2210		parseArray(c, 0, path[2:])
2211	} else {
2212		for ; i < len(c.json); i++ {
2213			if c.json[i] == '{' {
2214				i++
2215				parseObject(c, i, path)
2216				break
2217			}
2218			if c.json[i] == '[' {
2219				i++
2220				parseArray(c, i, path)
2221				break
2222			}
2223		}
2224	}
2225	if c.piped {
2226		res := c.value.Get(c.pipe)
2227		res.Index = 0
2228		return res
2229	}
2230	fillIndex(json, c)
2231	return c.value
2232}
2233
2234// GetBytes searches json for the specified path.
2235// If working with bytes, this method preferred over Get(string(data), path)
2236func GetBytes(json []byte, path string) Result {
2237	return getBytes(json, path)
2238}
2239
2240// runeit returns the rune from the the \uXXXX
2241func runeit(json string) rune {
2242	n, _ := strconv.ParseUint(json[:4], 16, 64)
2243	return rune(n)
2244}
2245
2246// unescape unescapes a string
2247func unescape(json string) string {
2248	var str = make([]byte, 0, len(json))
2249	for i := 0; i < len(json); i++ {
2250		switch {
2251		default:
2252			str = append(str, json[i])
2253		case json[i] < ' ':
2254			return string(str)
2255		case json[i] == '\\':
2256			i++
2257			if i >= len(json) {
2258				return string(str)
2259			}
2260			switch json[i] {
2261			default:
2262				return string(str)
2263			case '\\':
2264				str = append(str, '\\')
2265			case '/':
2266				str = append(str, '/')
2267			case 'b':
2268				str = append(str, '\b')
2269			case 'f':
2270				str = append(str, '\f')
2271			case 'n':
2272				str = append(str, '\n')
2273			case 'r':
2274				str = append(str, '\r')
2275			case 't':
2276				str = append(str, '\t')
2277			case '"':
2278				str = append(str, '"')
2279			case 'u':
2280				if i+5 > len(json) {
2281					return string(str)
2282				}
2283				r := runeit(json[i+1:])
2284				i += 5
2285				if utf16.IsSurrogate(r) {
2286					// need another code
2287					if len(json[i:]) >= 6 && json[i] == '\\' &&
2288						json[i+1] == 'u' {
2289						// we expect it to be correct so just consume it
2290						r = utf16.DecodeRune(r, runeit(json[i+2:]))
2291						i += 6
2292					}
2293				}
2294				// provide enough space to encode the largest utf8 possible
2295				str = append(str, 0, 0, 0, 0, 0, 0, 0, 0)
2296				n := utf8.EncodeRune(str[len(str)-8:], r)
2297				str = str[:len(str)-8+n]
2298				i-- // backtrack index by one
2299			}
2300		}
2301	}
2302	return string(str)
2303}
2304
2305// Less return true if a token is less than another token.
2306// The caseSensitive parameter is used when the tokens are Strings.
2307// The order when comparing two different type is:
2308//
2309//	Null < False < Number < String < True < JSON
2310func (t Result) Less(token Result, caseSensitive bool) bool {
2311	if t.Type < token.Type {
2312		return true
2313	}
2314	if t.Type > token.Type {
2315		return false
2316	}
2317	if t.Type == String {
2318		if caseSensitive {
2319			return t.Str < token.Str
2320		}
2321		return stringLessInsensitive(t.Str, token.Str)
2322	}
2323	if t.Type == Number {
2324		return t.Num < token.Num
2325	}
2326	return t.Raw < token.Raw
2327}
2328
2329func stringLessInsensitive(a, b string) bool {
2330	for i := 0; i < len(a) && i < len(b); i++ {
2331		if a[i] >= 'A' && a[i] <= 'Z' {
2332			if b[i] >= 'A' && b[i] <= 'Z' {
2333				// both are uppercase, do nothing
2334				if a[i] < b[i] {
2335					return true
2336				} else if a[i] > b[i] {
2337					return false
2338				}
2339			} else {
2340				// a is uppercase, convert a to lowercase
2341				if a[i]+32 < b[i] {
2342					return true
2343				} else if a[i]+32 > b[i] {
2344					return false
2345				}
2346			}
2347		} else if b[i] >= 'A' && b[i] <= 'Z' {
2348			// b is uppercase, convert b to lowercase
2349			if a[i] < b[i]+32 {
2350				return true
2351			} else if a[i] > b[i]+32 {
2352				return false
2353			}
2354		} else {
2355			// neither are uppercase
2356			if a[i] < b[i] {
2357				return true
2358			} else if a[i] > b[i] {
2359				return false
2360			}
2361		}
2362	}
2363	return len(a) < len(b)
2364}
2365
2366// parseAny parses the next value from a json string.
2367// A Result is returned when the hit param is set.
2368// The return values are (i int, res Result, ok bool)
2369func parseAny(json string, i int, hit bool) (int, Result, bool) {
2370	var res Result
2371	var val string
2372	for ; i < len(json); i++ {
2373		if json[i] == '{' || json[i] == '[' {
2374			i, val = parseSquash(json, i)
2375			if hit {
2376				res.Raw = val
2377				res.Type = JSON
2378			}
2379			var tmp parseContext
2380			tmp.value = res
2381			fillIndex(json, &tmp)
2382			return i, tmp.value, true
2383		}
2384		if json[i] <= ' ' {
2385			continue
2386		}
2387		var num bool
2388		switch json[i] {
2389		case '"':
2390			i++
2391			var vesc bool
2392			var ok bool
2393			i, val, vesc, ok = parseString(json, i)
2394			if !ok {
2395				return i, res, false
2396			}
2397			if hit {
2398				res.Type = String
2399				res.Raw = val
2400				if vesc {
2401					res.Str = unescape(val[1 : len(val)-1])
2402				} else {
2403					res.Str = val[1 : len(val)-1]
2404				}
2405			}
2406			return i, res, true
2407		case 'n':
2408			if i+1 < len(json) && json[i+1] != 'u' {
2409				num = true
2410				break
2411			}
2412			fallthrough
2413		case 't', 'f':
2414			vc := json[i]
2415			i, val = parseLiteral(json, i)
2416			if hit {
2417				res.Raw = val
2418				switch vc {
2419				case 't':
2420					res.Type = True
2421				case 'f':
2422					res.Type = False
2423				}
2424				return i, res, true
2425			}
2426		case '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2427			'i', 'I', 'N':
2428			num = true
2429		}
2430		if num {
2431			i, val = parseNumber(json, i)
2432			if hit {
2433				res.Raw = val
2434				res.Type = Number
2435				res.Num, _ = strconv.ParseFloat(val, 64)
2436			}
2437			return i, res, true
2438		}
2439
2440	}
2441	return i, res, false
2442}
2443
2444// GetMany searches json for the multiple paths.
2445// The return value is a Result array where the number of items
2446// will be equal to the number of input paths.
2447func GetMany(json string, path ...string) []Result {
2448	res := make([]Result, len(path))
2449	for i, path := range path {
2450		res[i] = Get(json, path)
2451	}
2452	return res
2453}
2454
2455// GetManyBytes searches json for the multiple paths.
2456// The return value is a Result array where the number of items
2457// will be equal to the number of input paths.
2458func GetManyBytes(json []byte, path ...string) []Result {
2459	res := make([]Result, len(path))
2460	for i, path := range path {
2461		res[i] = GetBytes(json, path)
2462	}
2463	return res
2464}
2465
2466func validpayload(data []byte, i int) (outi int, ok bool) {
2467	for ; i < len(data); i++ {
2468		switch data[i] {
2469		default:
2470			i, ok = validany(data, i)
2471			if !ok {
2472				return i, false
2473			}
2474			for ; i < len(data); i++ {
2475				switch data[i] {
2476				default:
2477					return i, false
2478				case ' ', '\t', '\n', '\r':
2479					continue
2480				}
2481			}
2482			return i, true
2483		case ' ', '\t', '\n', '\r':
2484			continue
2485		}
2486	}
2487	return i, false
2488}
2489func validany(data []byte, i int) (outi int, ok bool) {
2490	for ; i < len(data); i++ {
2491		switch data[i] {
2492		default:
2493			return i, false
2494		case ' ', '\t', '\n', '\r':
2495			continue
2496		case '{':
2497			return validobject(data, i+1)
2498		case '[':
2499			return validarray(data, i+1)
2500		case '"':
2501			return validstring(data, i+1)
2502		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
2503			return validnumber(data, i+1)
2504		case 't':
2505			return validtrue(data, i+1)
2506		case 'f':
2507			return validfalse(data, i+1)
2508		case 'n':
2509			return validnull(data, i+1)
2510		}
2511	}
2512	return i, false
2513}
2514func validobject(data []byte, i int) (outi int, ok bool) {
2515	for ; i < len(data); i++ {
2516		switch data[i] {
2517		default:
2518			return i, false
2519		case ' ', '\t', '\n', '\r':
2520			continue
2521		case '}':
2522			return i + 1, true
2523		case '"':
2524		key:
2525			if i, ok = validstring(data, i+1); !ok {
2526				return i, false
2527			}
2528			if i, ok = validcolon(data, i); !ok {
2529				return i, false
2530			}
2531			if i, ok = validany(data, i); !ok {
2532				return i, false
2533			}
2534			if i, ok = validcomma(data, i, '}'); !ok {
2535				return i, false
2536			}
2537			if data[i] == '}' {
2538				return i + 1, true
2539			}
2540			i++
2541			for ; i < len(data); i++ {
2542				switch data[i] {
2543				default:
2544					return i, false
2545				case ' ', '\t', '\n', '\r':
2546					continue
2547				case '"':
2548					goto key
2549				}
2550			}
2551			return i, false
2552		}
2553	}
2554	return i, false
2555}
2556func validcolon(data []byte, i int) (outi int, ok bool) {
2557	for ; i < len(data); i++ {
2558		switch data[i] {
2559		default:
2560			return i, false
2561		case ' ', '\t', '\n', '\r':
2562			continue
2563		case ':':
2564			return i + 1, true
2565		}
2566	}
2567	return i, false
2568}
2569func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
2570	for ; i < len(data); i++ {
2571		switch data[i] {
2572		default:
2573			return i, false
2574		case ' ', '\t', '\n', '\r':
2575			continue
2576		case ',':
2577			return i, true
2578		case end:
2579			return i, true
2580		}
2581	}
2582	return i, false
2583}
2584func validarray(data []byte, i int) (outi int, ok bool) {
2585	for ; i < len(data); i++ {
2586		switch data[i] {
2587		default:
2588			for ; i < len(data); i++ {
2589				if i, ok = validany(data, i); !ok {
2590					return i, false
2591				}
2592				if i, ok = validcomma(data, i, ']'); !ok {
2593					return i, false
2594				}
2595				if data[i] == ']' {
2596					return i + 1, true
2597				}
2598			}
2599		case ' ', '\t', '\n', '\r':
2600			continue
2601		case ']':
2602			return i + 1, true
2603		}
2604	}
2605	return i, false
2606}
2607func validstring(data []byte, i int) (outi int, ok bool) {
2608	for ; i < len(data); i++ {
2609		if data[i] < ' ' {
2610			return i, false
2611		} else if data[i] == '\\' {
2612			i++
2613			if i == len(data) {
2614				return i, false
2615			}
2616			switch data[i] {
2617			default:
2618				return i, false
2619			case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
2620			case 'u':
2621				for j := 0; j < 4; j++ {
2622					i++
2623					if i >= len(data) {
2624						return i, false
2625					}
2626					if !((data[i] >= '0' && data[i] <= '9') ||
2627						(data[i] >= 'a' && data[i] <= 'f') ||
2628						(data[i] >= 'A' && data[i] <= 'F')) {
2629						return i, false
2630					}
2631				}
2632			}
2633		} else if data[i] == '"' {
2634			return i + 1, true
2635		}
2636	}
2637	return i, false
2638}
2639func validnumber(data []byte, i int) (outi int, ok bool) {
2640	i--
2641	// sign
2642	if data[i] == '-' {
2643		i++
2644		if i == len(data) {
2645			return i, false
2646		}
2647		if data[i] < '0' || data[i] > '9' {
2648			return i, false
2649		}
2650	}
2651	// int
2652	if i == len(data) {
2653		return i, false
2654	}
2655	if data[i] == '0' {
2656		i++
2657	} else {
2658		for ; i < len(data); i++ {
2659			if data[i] >= '0' && data[i] <= '9' {
2660				continue
2661			}
2662			break
2663		}
2664	}
2665	// frac
2666	if i == len(data) {
2667		return i, true
2668	}
2669	if data[i] == '.' {
2670		i++
2671		if i == len(data) {
2672			return i, false
2673		}
2674		if data[i] < '0' || data[i] > '9' {
2675			return i, false
2676		}
2677		i++
2678		for ; i < len(data); i++ {
2679			if data[i] >= '0' && data[i] <= '9' {
2680				continue
2681			}
2682			break
2683		}
2684	}
2685	// exp
2686	if i == len(data) {
2687		return i, true
2688	}
2689	if data[i] == 'e' || data[i] == 'E' {
2690		i++
2691		if i == len(data) {
2692			return i, false
2693		}
2694		if data[i] == '+' || data[i] == '-' {
2695			i++
2696		}
2697		if i == len(data) {
2698			return i, false
2699		}
2700		if data[i] < '0' || data[i] > '9' {
2701			return i, false
2702		}
2703		i++
2704		for ; i < len(data); i++ {
2705			if data[i] >= '0' && data[i] <= '9' {
2706				continue
2707			}
2708			break
2709		}
2710	}
2711	return i, true
2712}
2713
2714func validtrue(data []byte, i int) (outi int, ok bool) {
2715	if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' &&
2716		data[i+2] == 'e' {
2717		return i + 3, true
2718	}
2719	return i, false
2720}
2721func validfalse(data []byte, i int) (outi int, ok bool) {
2722	if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' &&
2723		data[i+2] == 's' && data[i+3] == 'e' {
2724		return i + 4, true
2725	}
2726	return i, false
2727}
2728func validnull(data []byte, i int) (outi int, ok bool) {
2729	if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' &&
2730		data[i+2] == 'l' {
2731		return i + 3, true
2732	}
2733	return i, false
2734}
2735
2736// Valid returns true if the input is valid json.
2737//
2738//	if !gjson.Valid(json) {
2739//		return errors.New("invalid json")
2740//	}
2741//	value := gjson.Get(json, "name.last")
2742func Valid(json string) bool {
2743	_, ok := validpayload(stringBytes(json), 0)
2744	return ok
2745}
2746
2747// ValidBytes returns true if the input is valid json.
2748//
2749//	if !gjson.Valid(json) {
2750//		return errors.New("invalid json")
2751//	}
2752//	value := gjson.Get(json, "name.last")
2753//
2754// If working with bytes, this method preferred over ValidBytes(string(data))
2755func ValidBytes(json []byte) bool {
2756	_, ok := validpayload(json, 0)
2757	return ok
2758}
2759
2760func parseUint(s string) (n uint64, ok bool) {
2761	var i int
2762	if i == len(s) {
2763		return 0, false
2764	}
2765	for ; i < len(s); i++ {
2766		if s[i] >= '0' && s[i] <= '9' {
2767			n = n*10 + uint64(s[i]-'0')
2768		} else {
2769			return 0, false
2770		}
2771	}
2772	return n, true
2773}
2774
2775func parseInt(s string) (n int64, ok bool) {
2776	var i int
2777	var sign bool
2778	if len(s) > 0 && s[0] == '-' {
2779		sign = true
2780		i++
2781	}
2782	if i == len(s) {
2783		return 0, false
2784	}
2785	for ; i < len(s); i++ {
2786		if s[i] >= '0' && s[i] <= '9' {
2787			n = n*10 + int64(s[i]-'0')
2788		} else {
2789			return 0, false
2790		}
2791	}
2792	if sign {
2793		return n * -1, true
2794	}
2795	return n, true
2796}
2797
2798// safeInt validates a given JSON number
2799// ensures it lies within the minimum and maximum representable JSON numbers
2800func safeInt(f float64) (n int64, ok bool) {
2801	// https://tc39.es/ecma262/#sec-number.min_safe_integer
2802	// https://tc39.es/ecma262/#sec-number.max_safe_integer
2803	if f < -9007199254740991 || f > 9007199254740991 {
2804		return 0, false
2805	}
2806	return int64(f), true
2807}
2808
2809// execStatic parses the path to find a static value.
2810// The input expects that the path already starts with a '!'
2811func execStatic(json, path string) (pathOut, res string, ok bool) {
2812	name := path[1:]
2813	if len(name) > 0 {
2814		switch name[0] {
2815		case '{', '[', '"', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7',
2816			'8', '9':
2817			_, res = parseSquash(name, 0)
2818			pathOut = name[len(res):]
2819			return pathOut, res, true
2820		}
2821	}
2822	for i := 1; i < len(path); i++ {
2823		if path[i] == '|' {
2824			pathOut = path[i:]
2825			name = path[1:i]
2826			break
2827		}
2828		if path[i] == '.' {
2829			pathOut = path[i:]
2830			name = path[1:i]
2831			break
2832		}
2833	}
2834	switch strings.ToLower(name) {
2835	case "true", "false", "null", "nan", "inf":
2836		return pathOut, name, true
2837	}
2838	return pathOut, res, false
2839}
2840
2841// execModifier parses the path to find a matching modifier function.
2842// The input expects that the path already starts with a '@'
2843func execModifier(json, path string) (pathOut, res string, ok bool) {
2844	name := path[1:]
2845	var hasArgs bool
2846	for i := 1; i < len(path); i++ {
2847		if path[i] == ':' {
2848			pathOut = path[i+1:]
2849			name = path[1:i]
2850			hasArgs = len(pathOut) > 0
2851			break
2852		}
2853		if path[i] == '|' {
2854			pathOut = path[i:]
2855			name = path[1:i]
2856			break
2857		}
2858		if path[i] == '.' {
2859			pathOut = path[i:]
2860			name = path[1:i]
2861			break
2862		}
2863	}
2864	if fn, ok := modifiers[name]; ok {
2865		var args string
2866		if hasArgs {
2867			var parsedArgs bool
2868			switch pathOut[0] {
2869			case '{', '[', '"':
2870				// json arg
2871				res := Parse(pathOut)
2872				if res.Exists() {
2873					args = squash(pathOut)
2874					pathOut = pathOut[len(args):]
2875					parsedArgs = true
2876				}
2877			}
2878			if !parsedArgs {
2879				// simple arg
2880				i := 0
2881				for ; i < len(pathOut); i++ {
2882					if pathOut[i] == '|' {
2883						break
2884					}
2885					switch pathOut[i] {
2886					case '{', '[', '"', '(':
2887						s := squash(pathOut[i:])
2888						i += len(s) - 1
2889					}
2890				}
2891				args = pathOut[:i]
2892				pathOut = pathOut[i:]
2893			}
2894		}
2895		return pathOut, fn(json, args), true
2896	}
2897	return pathOut, res, false
2898}
2899
2900// unwrap removes the '[]' or '{}' characters around json
2901func unwrap(json string) string {
2902	json = trim(json)
2903	if len(json) >= 2 && (json[0] == '[' || json[0] == '{') {
2904		json = json[1 : len(json)-1]
2905	}
2906	return json
2907}
2908
2909// DisableModifiers will disable the modifier syntax
2910var DisableModifiers = false
2911
2912var modifiers map[string]func(json, arg string) string
2913
2914func init() {
2915	modifiers = map[string]func(json, arg string) string{
2916		"pretty":  modPretty,
2917		"ugly":    modUgly,
2918		"reverse": modReverse,
2919		"this":    modThis,
2920		"flatten": modFlatten,
2921		"join":    modJoin,
2922		"valid":   modValid,
2923		"keys":    modKeys,
2924		"values":  modValues,
2925		"tostr":   modToStr,
2926		"fromstr": modFromStr,
2927		"group":   modGroup,
2928		"dig":     modDig,
2929	}
2930}
2931
2932// AddModifier binds a custom modifier command to the GJSON syntax.
2933// This operation is not thread safe and should be executed prior to
2934// using all other gjson function.
2935func AddModifier(name string, fn func(json, arg string) string) {
2936	modifiers[name] = fn
2937}
2938
2939// ModifierExists returns true when the specified modifier exists.
2940func ModifierExists(name string, fn func(json, arg string) string) bool {
2941	_, ok := modifiers[name]
2942	return ok
2943}
2944
2945// cleanWS remove any non-whitespace from string
2946func cleanWS(s string) string {
2947	for i := 0; i < len(s); i++ {
2948		switch s[i] {
2949		case ' ', '\t', '\n', '\r':
2950			continue
2951		default:
2952			var s2 []byte
2953			for i := 0; i < len(s); i++ {
2954				switch s[i] {
2955				case ' ', '\t', '\n', '\r':
2956					s2 = append(s2, s[i])
2957				}
2958			}
2959			return string(s2)
2960		}
2961	}
2962	return s
2963}
2964
2965// @pretty modifier makes the json look nice.
2966func modPretty(json, arg string) string {
2967	if len(arg) > 0 {
2968		opts := *pretty.DefaultOptions
2969		Parse(arg).ForEach(func(key, value Result) bool {
2970			switch key.String() {
2971			case "sortKeys":
2972				opts.SortKeys = value.Bool()
2973			case "indent":
2974				opts.Indent = cleanWS(value.String())
2975			case "prefix":
2976				opts.Prefix = cleanWS(value.String())
2977			case "width":
2978				opts.Width = int(value.Int())
2979			}
2980			return true
2981		})
2982		return bytesString(pretty.PrettyOptions(stringBytes(json), &opts))
2983	}
2984	return bytesString(pretty.Pretty(stringBytes(json)))
2985}
2986
2987// @this returns the current element. Can be used to retrieve the root element.
2988func modThis(json, arg string) string {
2989	return json
2990}
2991
2992// @ugly modifier removes all whitespace.
2993func modUgly(json, arg string) string {
2994	return bytesString(pretty.Ugly(stringBytes(json)))
2995}
2996
2997// @reverse reverses array elements or root object members.
2998func modReverse(json, arg string) string {
2999	res := Parse(json)
3000	if res.IsArray() {
3001		var values []Result
3002		res.ForEach(func(_, value Result) bool {
3003			values = append(values, value)
3004			return true
3005		})
3006		out := make([]byte, 0, len(json))
3007		out = append(out, '[')
3008		for i, j := len(values)-1, 0; i >= 0; i, j = i-1, j+1 {
3009			if j > 0 {
3010				out = append(out, ',')
3011			}
3012			out = append(out, values[i].Raw...)
3013		}
3014		out = append(out, ']')
3015		return bytesString(out)
3016	}
3017	if res.IsObject() {
3018		var keyValues []Result
3019		res.ForEach(func(key, value Result) bool {
3020			keyValues = append(keyValues, key, value)
3021			return true
3022		})
3023		out := make([]byte, 0, len(json))
3024		out = append(out, '{')
3025		for i, j := len(keyValues)-2, 0; i >= 0; i, j = i-2, j+1 {
3026			if j > 0 {
3027				out = append(out, ',')
3028			}
3029			out = append(out, keyValues[i+0].Raw...)
3030			out = append(out, ':')
3031			out = append(out, keyValues[i+1].Raw...)
3032		}
3033		out = append(out, '}')
3034		return bytesString(out)
3035	}
3036	return json
3037}
3038
3039// @flatten an array with child arrays.
3040//
3041//	[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,[6,7]]
3042//
3043// The {"deep":true} arg can be provide for deep flattening.
3044//
3045//	[1,[2],[3,4],[5,[6,7]]] -> [1,2,3,4,5,6,7]
3046//
3047// The original json is returned when the json is not an array.
3048func modFlatten(json, arg string) string {
3049	res := Parse(json)
3050	if !res.IsArray() {
3051		return json
3052	}
3053	var deep bool
3054	if arg != "" {
3055		Parse(arg).ForEach(func(key, value Result) bool {
3056			if key.String() == "deep" {
3057				deep = value.Bool()
3058			}
3059			return true
3060		})
3061	}
3062	var out []byte
3063	out = append(out, '[')
3064	var idx int
3065	res.ForEach(func(_, value Result) bool {
3066		var raw string
3067		if value.IsArray() {
3068			if deep {
3069				raw = unwrap(modFlatten(value.Raw, arg))
3070			} else {
3071				raw = unwrap(value.Raw)
3072			}
3073		} else {
3074			raw = value.Raw
3075		}
3076		raw = strings.TrimSpace(raw)
3077		if len(raw) > 0 {
3078			if idx > 0 {
3079				out = append(out, ',')
3080			}
3081			out = append(out, raw...)
3082			idx++
3083		}
3084		return true
3085	})
3086	out = append(out, ']')
3087	return bytesString(out)
3088}
3089
3090// @keys extracts the keys from an object.
3091//
3092//	{"first":"Tom","last":"Smith"} -> ["first","last"]
3093func modKeys(json, arg string) string {
3094	v := Parse(json)
3095	if !v.Exists() {
3096		return "[]"
3097	}
3098	obj := v.IsObject()
3099	var out strings.Builder
3100	out.WriteByte('[')
3101	var i int
3102	v.ForEach(func(key, _ Result) bool {
3103		if i > 0 {
3104			out.WriteByte(',')
3105		}
3106		if obj {
3107			out.WriteString(key.Raw)
3108		} else {
3109			out.WriteString("null")
3110		}
3111		i++
3112		return true
3113	})
3114	out.WriteByte(']')
3115	return out.String()
3116}
3117
3118// @values extracts the values from an object.
3119//
3120//	{"first":"Tom","last":"Smith"} -> ["Tom","Smith"]
3121func modValues(json, arg string) string {
3122	v := Parse(json)
3123	if !v.Exists() {
3124		return "[]"
3125	}
3126	if v.IsArray() {
3127		return json
3128	}
3129	var out strings.Builder
3130	out.WriteByte('[')
3131	var i int
3132	v.ForEach(func(_, value Result) bool {
3133		if i > 0 {
3134			out.WriteByte(',')
3135		}
3136		out.WriteString(value.Raw)
3137		i++
3138		return true
3139	})
3140	out.WriteByte(']')
3141	return out.String()
3142}
3143
3144// @join multiple objects into a single object.
3145//
3146//	[{"first":"Tom"},{"last":"Smith"}] -> {"first","Tom","last":"Smith"}
3147//
3148// The arg can be "true" to specify that duplicate keys should be preserved.
3149//
3150//	[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":37,"age":41}
3151//
3152// Without preserved keys:
3153//
3154//	[{"first":"Tom","age":37},{"age":41}] -> {"first","Tom","age":41}
3155//
3156// The original json is returned when the json is not an object.
3157func modJoin(json, arg string) string {
3158	res := Parse(json)
3159	if !res.IsArray() {
3160		return json
3161	}
3162	var preserve bool
3163	if arg != "" {
3164		Parse(arg).ForEach(func(key, value Result) bool {
3165			if key.String() == "preserve" {
3166				preserve = value.Bool()
3167			}
3168			return true
3169		})
3170	}
3171	var out []byte
3172	out = append(out, '{')
3173	if preserve {
3174		// Preserve duplicate keys.
3175		var idx int
3176		res.ForEach(func(_, value Result) bool {
3177			if !value.IsObject() {
3178				return true
3179			}
3180			if idx > 0 {
3181				out = append(out, ',')
3182			}
3183			out = append(out, unwrap(value.Raw)...)
3184			idx++
3185			return true
3186		})
3187	} else {
3188		// Deduplicate keys and generate an object with stable ordering.
3189		var keys []Result
3190		kvals := make(map[string]Result)
3191		res.ForEach(func(_, value Result) bool {
3192			if !value.IsObject() {
3193				return true
3194			}
3195			value.ForEach(func(key, value Result) bool {
3196				k := key.String()
3197				if _, ok := kvals[k]; !ok {
3198					keys = append(keys, key)
3199				}
3200				kvals[k] = value
3201				return true
3202			})
3203			return true
3204		})
3205		for i := 0; i < len(keys); i++ {
3206			if i > 0 {
3207				out = append(out, ',')
3208			}
3209			out = append(out, keys[i].Raw...)
3210			out = append(out, ':')
3211			out = append(out, kvals[keys[i].String()].Raw...)
3212		}
3213	}
3214	out = append(out, '}')
3215	return bytesString(out)
3216}
3217
3218// @valid ensures that the json is valid before moving on. An empty string is
3219// returned when the json is not valid, otherwise it returns the original json.
3220func modValid(json, arg string) string {
3221	if !Valid(json) {
3222		return ""
3223	}
3224	return json
3225}
3226
3227// @fromstr converts a string to json
3228//
3229//	"{\"id\":1023,\"name\":\"alert\"}" -> {"id":1023,"name":"alert"}
3230func modFromStr(json, arg string) string {
3231	if !Valid(json) {
3232		return ""
3233	}
3234	return Parse(json).String()
3235}
3236
3237// @tostr converts a string to json
3238//
3239//	{"id":1023,"name":"alert"} -> "{\"id\":1023,\"name\":\"alert\"}"
3240func modToStr(str, arg string) string {
3241	return string(AppendJSONString(nil, str))
3242}
3243
3244func modGroup(json, arg string) string {
3245	res := Parse(json)
3246	if !res.IsObject() {
3247		return ""
3248	}
3249	var all [][]byte
3250	res.ForEach(func(key, value Result) bool {
3251		if !value.IsArray() {
3252			return true
3253		}
3254		var idx int
3255		value.ForEach(func(_, value Result) bool {
3256			if idx == len(all) {
3257				all = append(all, []byte{})
3258			}
3259			all[idx] = append(all[idx], ("," + key.Raw + ":" + value.Raw)...)
3260			idx++
3261			return true
3262		})
3263		return true
3264	})
3265	var data []byte
3266	data = append(data, '[')
3267	for i, item := range all {
3268		if i > 0 {
3269			data = append(data, ',')
3270		}
3271		data = append(data, '{')
3272		data = append(data, item[1:]...)
3273		data = append(data, '}')
3274	}
3275	data = append(data, ']')
3276	return string(data)
3277}
3278
3279// stringHeader instead of reflect.StringHeader
3280type stringHeader struct {
3281	data unsafe.Pointer
3282	len  int
3283}
3284
3285// sliceHeader instead of reflect.SliceHeader
3286type sliceHeader struct {
3287	data unsafe.Pointer
3288	len  int
3289	cap  int
3290}
3291
3292// getBytes casts the input json bytes to a string and safely returns the
3293// results as uniquely allocated data. This operation is intended to minimize
3294// copies and allocations for the large json string->[]byte.
3295func getBytes(json []byte, path string) Result {
3296	var result Result
3297	if json != nil {
3298		// unsafe cast to string
3299		result = Get(*(*string)(unsafe.Pointer(&json)), path)
3300		// safely get the string headers
3301		rawhi := *(*stringHeader)(unsafe.Pointer(&result.Raw))
3302		strhi := *(*stringHeader)(unsafe.Pointer(&result.Str))
3303		// create byte slice headers
3304		rawh := sliceHeader{data: rawhi.data, len: rawhi.len, cap: rawhi.len}
3305		strh := sliceHeader{data: strhi.data, len: strhi.len, cap: rawhi.len}
3306		if strh.data == nil {
3307			// str is nil
3308			if rawh.data == nil {
3309				// raw is nil
3310				result.Raw = ""
3311			} else {
3312				// raw has data, safely copy the slice header to a string
3313				result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3314			}
3315			result.Str = ""
3316		} else if rawh.data == nil {
3317			// raw is nil
3318			result.Raw = ""
3319			// str has data, safely copy the slice header to a string
3320			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
3321		} else if uintptr(strh.data) >= uintptr(rawh.data) &&
3322			uintptr(strh.data)+uintptr(strh.len) <=
3323				uintptr(rawh.data)+uintptr(rawh.len) {
3324			// Str is a substring of Raw.
3325			start := uintptr(strh.data) - uintptr(rawh.data)
3326			// safely copy the raw slice header
3327			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3328			// substring the raw
3329			result.Str = result.Raw[start : start+uintptr(strh.len)]
3330		} else {
3331			// safely copy both the raw and str slice headers to strings
3332			result.Raw = string(*(*[]byte)(unsafe.Pointer(&rawh)))
3333			result.Str = string(*(*[]byte)(unsafe.Pointer(&strh)))
3334		}
3335	}
3336	return result
3337}
3338
3339// fillIndex finds the position of Raw data and assigns it to the Index field
3340// of the resulting value. If the position cannot be found then Index zero is
3341// used instead.
3342func fillIndex(json string, c *parseContext) {
3343	if len(c.value.Raw) > 0 && !c.calcd {
3344		jhdr := *(*stringHeader)(unsafe.Pointer(&json))
3345		rhdr := *(*stringHeader)(unsafe.Pointer(&(c.value.Raw)))
3346		c.value.Index = int(uintptr(rhdr.data) - uintptr(jhdr.data))
3347		if c.value.Index < 0 || c.value.Index >= len(json) {
3348			c.value.Index = 0
3349		}
3350	}
3351}
3352
3353func stringBytes(s string) []byte {
3354	return *(*[]byte)(unsafe.Pointer(&sliceHeader{
3355		data: (*stringHeader)(unsafe.Pointer(&s)).data,
3356		len:  len(s),
3357		cap:  len(s),
3358	}))
3359}
3360
3361func bytesString(b []byte) string {
3362	return *(*string)(unsafe.Pointer(&b))
3363}
3364
3365func revSquash(json string) string {
3366	// reverse squash
3367	// expects that the tail character is a ']' or '}' or ')' or '"'
3368	// squash the value, ignoring all nested arrays and objects.
3369	i := len(json) - 1
3370	var depth int
3371	if json[i] != '"' {
3372		depth++
3373	}
3374	if json[i] == '}' || json[i] == ']' || json[i] == ')' {
3375		i--
3376	}
3377	for ; i >= 0; i-- {
3378		switch json[i] {
3379		case '"':
3380			i--
3381			for ; i >= 0; i-- {
3382				if json[i] == '"' {
3383					esc := 0
3384					for i > 0 && json[i-1] == '\\' {
3385						i--
3386						esc++
3387					}
3388					if esc%2 == 1 {
3389						continue
3390					}
3391					i += esc
3392					break
3393				}
3394			}
3395			if depth == 0 {
3396				if i < 0 {
3397					i = 0
3398				}
3399				return json[i:]
3400			}
3401		case '}', ']', ')':
3402			depth++
3403		case '{', '[', '(':
3404			depth--
3405			if depth == 0 {
3406				return json[i:]
3407			}
3408		}
3409	}
3410	return json
3411}
3412
3413// Paths returns the original GJSON paths for a Result where the Result came
3414// from a simple query path that returns an array, like:
3415//
3416//	gjson.Get(json, "friends.#.first")
3417//
3418// The returned value will be in the form of a JSON array:
3419//
3420//	["friends.0.first","friends.1.first","friends.2.first"]
3421//
3422// The param 'json' must be the original JSON used when calling Get.
3423//
3424// Returns an empty string if the paths cannot be determined, which can happen
3425// when the Result came from a path that contained a multipath, modifier,
3426// or a nested query.
3427func (t Result) Paths(json string) []string {
3428	if t.Indexes == nil {
3429		return nil
3430	}
3431	paths := make([]string, 0, len(t.Indexes))
3432	t.ForEach(func(_, value Result) bool {
3433		paths = append(paths, value.Path(json))
3434		return true
3435	})
3436	if len(paths) != len(t.Indexes) {
3437		return nil
3438	}
3439	return paths
3440}
3441
3442// Path returns the original GJSON path for a Result where the Result came
3443// from a simple path that returns a single value, like:
3444//
3445//	gjson.Get(json, "friends.#(last=Murphy)")
3446//
3447// The returned value will be in the form of a JSON string:
3448//
3449//	"friends.0"
3450//
3451// The param 'json' must be the original JSON used when calling Get.
3452//
3453// Returns an empty string if the paths cannot be determined, which can happen
3454// when the Result came from a path that contained a multipath, modifier,
3455// or a nested query.
3456func (t Result) Path(json string) string {
3457	var path []byte
3458	var comps []string // raw components
3459	i := t.Index - 1
3460	if t.Index+len(t.Raw) > len(json) {
3461		// JSON cannot safely contain Result.
3462		goto fail
3463	}
3464	if !strings.HasPrefix(json[t.Index:], t.Raw) {
3465		// Result is not at the JSON index as expected.
3466		goto fail
3467	}
3468	for ; i >= 0; i-- {
3469		if json[i] <= ' ' {
3470			continue
3471		}
3472		if json[i] == ':' {
3473			// inside of object, get the key
3474			for ; i >= 0; i-- {
3475				if json[i] != '"' {
3476					continue
3477				}
3478				break
3479			}
3480			raw := revSquash(json[:i+1])
3481			i = i - len(raw)
3482			comps = append(comps, raw)
3483			// key gotten, now squash the rest
3484			raw = revSquash(json[:i+1])
3485			i = i - len(raw)
3486			i++ // increment the index for next loop step
3487		} else if json[i] == '{' {
3488			// Encountered an open object. The original result was probably an
3489			// object key.
3490			goto fail
3491		} else if json[i] == ',' || json[i] == '[' {
3492			// inside of an array, count the position
3493			var arrIdx int
3494			if json[i] == ',' {
3495				arrIdx++
3496				i--
3497			}
3498			for ; i >= 0; i-- {
3499				if json[i] == ':' {
3500					// Encountered an unexpected colon. The original result was
3501					// probably an object key.
3502					goto fail
3503				} else if json[i] == ',' {
3504					arrIdx++
3505				} else if json[i] == '[' {
3506					comps = append(comps, strconv.Itoa(arrIdx))
3507					break
3508				} else if json[i] == ']' || json[i] == '}' || json[i] == '"' {
3509					raw := revSquash(json[:i+1])
3510					i = i - len(raw) + 1
3511				}
3512			}
3513		}
3514	}
3515	if len(comps) == 0 {
3516		if DisableModifiers {
3517			goto fail
3518		}
3519		return "@this"
3520	}
3521	for i := len(comps) - 1; i >= 0; i-- {
3522		rcomp := Parse(comps[i])
3523		if !rcomp.Exists() {
3524			goto fail
3525		}
3526		comp := Escape(rcomp.String())
3527		path = append(path, '.')
3528		path = append(path, comp...)
3529	}
3530	if len(path) > 0 {
3531		path = path[1:]
3532	}
3533	return string(path)
3534fail:
3535	return ""
3536}
3537
3538// isSafePathKeyChar returns true if the input character is safe for not
3539// needing escaping.
3540func isSafePathKeyChar(c byte) bool {
3541	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
3542		(c >= '0' && c <= '9') || c <= ' ' || c > '~' || c == '_' ||
3543		c == '-' || c == ':'
3544}
3545
3546// Escape returns an escaped path component.
3547//
3548//	json := `{
3549//	  "user":{
3550//	     "first.name": "Janet",
3551//	     "last.name": "Prichard"
3552//	   }
3553//	}`
3554//	user := gjson.Get(json, "user")
3555//	println(user.Get(gjson.Escape("first.name"))
3556//	println(user.Get(gjson.Escape("last.name"))
3557//	// Output:
3558//	// Janet
3559//	// Prichard
3560func Escape(comp string) string {
3561	for i := 0; i < len(comp); i++ {
3562		if !isSafePathKeyChar(comp[i]) {
3563			ncomp := make([]byte, len(comp)+1)
3564			copy(ncomp, comp[:i])
3565			ncomp = ncomp[:i]
3566			for ; i < len(comp); i++ {
3567				if !isSafePathKeyChar(comp[i]) {
3568					ncomp = append(ncomp, '\\')
3569				}
3570				ncomp = append(ncomp, comp[i])
3571			}
3572			return string(ncomp)
3573		}
3574	}
3575	return comp
3576}
3577
3578func parseRecursiveDescent(all []Result, parent Result, path string) []Result {
3579	if res := parent.Get(path); res.Exists() {
3580		all = append(all, res)
3581	}
3582	if parent.IsArray() || parent.IsObject() {
3583		parent.ForEach(func(_, val Result) bool {
3584			all = parseRecursiveDescent(all, val, path)
3585			return true
3586		})
3587	}
3588	return all
3589}
3590
3591func modDig(json, arg string) string {
3592	all := parseRecursiveDescent(nil, Parse(json), arg)
3593	var out []byte
3594	out = append(out, '[')
3595	for i, res := range all {
3596		if i > 0 {
3597			out = append(out, ',')
3598		}
3599		out = append(out, res.Raw...)
3600	}
3601	out = append(out, ']')
3602	return string(out)
3603}