mirror of https://github.com/tidwall/gjson.git
parent
d6d786db3c
commit
d9710733f0
25
gjson.go
25
gjson.go
|
@ -714,10 +714,10 @@ type arrayPathResult struct {
|
||||||
alogkey string
|
alogkey string
|
||||||
query struct {
|
query struct {
|
||||||
on bool
|
on bool
|
||||||
|
all bool
|
||||||
path string
|
path string
|
||||||
op string
|
op string
|
||||||
value string
|
value string
|
||||||
all bool
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,14 +750,23 @@ func parseArrayPath(path string) (r arrayPathResult) {
|
||||||
} else if path[1] == '[' || path[1] == '(' {
|
} else if path[1] == '[' || path[1] == '(' {
|
||||||
// query
|
// query
|
||||||
r.query.on = true
|
r.query.on = true
|
||||||
qpath, op, value, _, fi, ok := parseQuery(path[i:])
|
qpath, op, value, _, fi, vesc, ok :=
|
||||||
|
parseQuery(path[i:])
|
||||||
if !ok {
|
if !ok {
|
||||||
// bad query, end now
|
// bad query, end now
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if len(value) > 2 && value[0] == '"' &&
|
||||||
|
value[len(value)-1] == '"' {
|
||||||
|
value = value[1 : len(value)-1]
|
||||||
|
if vesc {
|
||||||
|
value = unescape(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
r.query.path = qpath
|
r.query.path = qpath
|
||||||
r.query.op = op
|
r.query.op = op
|
||||||
r.query.value = value
|
r.query.value = value
|
||||||
|
|
||||||
i = fi - 1
|
i = fi - 1
|
||||||
if i+1 < len(path) && path[i+1] == '#' {
|
if i+1 < len(path) && path[i+1] == '#' {
|
||||||
r.query.all = true
|
r.query.all = true
|
||||||
|
@ -787,11 +796,11 @@ func parseArrayPath(path string) (r arrayPathResult) {
|
||||||
// # middle
|
// # middle
|
||||||
// .cap # right
|
// .cap # right
|
||||||
func parseQuery(query string) (
|
func parseQuery(query string) (
|
||||||
path, op, value, remain string, i int, ok bool,
|
path, op, value, remain string, i int, vesc, ok bool,
|
||||||
) {
|
) {
|
||||||
if len(query) < 2 || query[0] != '#' ||
|
if len(query) < 2 || query[0] != '#' ||
|
||||||
(query[1] != '(' && query[1] != '[') {
|
(query[1] != '(' && query[1] != '[') {
|
||||||
return "", "", "", "", i, false
|
return "", "", "", "", i, false, false
|
||||||
}
|
}
|
||||||
i = 2
|
i = 2
|
||||||
j := 0 // start of value part
|
j := 0 // start of value part
|
||||||
|
@ -819,6 +828,7 @@ func parseQuery(query string) (
|
||||||
i++
|
i++
|
||||||
for ; i < len(query); i++ {
|
for ; i < len(query); i++ {
|
||||||
if query[i] == '\\' {
|
if query[i] == '\\' {
|
||||||
|
vesc = true
|
||||||
i++
|
i++
|
||||||
} else if query[i] == '"' {
|
} else if query[i] == '"' {
|
||||||
break
|
break
|
||||||
|
@ -827,7 +837,7 @@ func parseQuery(query string) (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if depth > 0 {
|
if depth > 0 {
|
||||||
return "", "", "", "", i, false
|
return "", "", "", "", i, false, false
|
||||||
}
|
}
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
path = trim(query[2:j])
|
path = trim(query[2:j])
|
||||||
|
@ -864,7 +874,7 @@ func parseQuery(query string) (
|
||||||
path = trim(query[2:i])
|
path = trim(query[2:i])
|
||||||
remain = query[i+1:]
|
remain = query[i+1:]
|
||||||
}
|
}
|
||||||
return path, op, value, remain, i + 1, true
|
return path, op, value, remain, i + 1, vesc, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func trim(s string) string {
|
func trim(s string) string {
|
||||||
|
@ -1164,9 +1174,6 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
|
||||||
}
|
}
|
||||||
func queryMatches(rp *arrayPathResult, value Result) bool {
|
func queryMatches(rp *arrayPathResult, value Result) bool {
|
||||||
rpv := rp.query.value
|
rpv := rp.query.value
|
||||||
if len(rpv) > 2 && rpv[0] == '"' && rpv[len(rpv)-1] == '"' {
|
|
||||||
rpv = rpv[1 : len(rpv)-1]
|
|
||||||
}
|
|
||||||
if !value.Exists() {
|
if !value.Exists() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1741,7 +1741,7 @@ func TestParseQuery(t *testing.T) {
|
||||||
var path, op, value, remain string
|
var path, op, value, remain string
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
path, op, value, remain, _, ok =
|
path, op, value, remain, _, _, ok =
|
||||||
parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
|
parseQuery(`#(service_roles.#(=="one").()==asdf).cap`)
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `service_roles.#(=="one").()` &&
|
path == `service_roles.#(=="one").()` &&
|
||||||
|
@ -1749,28 +1749,28 @@ func TestParseQuery(t *testing.T) {
|
||||||
value == `asdf` &&
|
value == `asdf` &&
|
||||||
remain == `.cap`)
|
remain == `.cap`)
|
||||||
|
|
||||||
path, op, value, remain, _, ok = parseQuery(`#(first_name%"Murphy").last`)
|
path, op, value, remain, _, _, ok = parseQuery(`#(first_name%"Murphy").last`)
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `first_name` &&
|
path == `first_name` &&
|
||||||
op == `%` &&
|
op == `%` &&
|
||||||
value == `"Murphy"` &&
|
value == `"Murphy"` &&
|
||||||
remain == `.last`)
|
remain == `.last`)
|
||||||
|
|
||||||
path, op, value, remain, _, ok = parseQuery(`#( first_name !% "Murphy" ).last`)
|
path, op, value, remain, _, _, ok = parseQuery(`#( first_name !% "Murphy" ).last`)
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `first_name` &&
|
path == `first_name` &&
|
||||||
op == `!%` &&
|
op == `!%` &&
|
||||||
value == `"Murphy"` &&
|
value == `"Murphy"` &&
|
||||||
remain == `.last`)
|
remain == `.last`)
|
||||||
|
|
||||||
path, op, value, remain, _, ok = parseQuery(`#(service_roles.#(=="one"))`)
|
path, op, value, remain, _, _, ok = parseQuery(`#(service_roles.#(=="one"))`)
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `service_roles.#(=="one")` &&
|
path == `service_roles.#(=="one")` &&
|
||||||
op == `` &&
|
op == `` &&
|
||||||
value == `` &&
|
value == `` &&
|
||||||
remain == ``)
|
remain == ``)
|
||||||
|
|
||||||
path, op, value, remain, _, ok =
|
path, op, value, remain, _, _, ok =
|
||||||
parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
|
parseQuery(`#(a\("\"(".#(=="o\"(ne")%"ab\")").remain`)
|
||||||
assert(t, ok &&
|
assert(t, ok &&
|
||||||
path == `a\("\"(".#(=="o\"(ne")` &&
|
path == `a\("\"(".#(=="o\"(ne")` &&
|
||||||
|
@ -2052,3 +2052,15 @@ func TestPipeEmptyArray(t *testing.T) {
|
||||||
raw := Get("[]", `#(hello)#`).Raw
|
raw := Get("[]", `#(hello)#`).Raw
|
||||||
assert(t, raw == "[]")
|
assert(t, raw == "[]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEncodedQueryString(t *testing.T) {
|
||||||
|
json := `{
|
||||||
|
"friends": [
|
||||||
|
{"first": "Dale", "last": "Mur\nphy", "age": 44},
|
||||||
|
{"first": "Roger", "last": "Craig", "age": 68},
|
||||||
|
{"first": "Jane", "last": "Murphy", "age": 47}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
assert(t, Get(json, `friends.#(last=="Mur\nphy").age`).Int() == 44)
|
||||||
|
assert(t, Get(json, `friends.#(last=="Murphy").age`).Int() == 47)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue