From 00b15d756ea6c964af63931b03acf44ab52d991a Mon Sep 17 00:00:00 2001 From: tidwall Date: Fri, 28 Jun 2019 05:55:18 -0700 Subject: [PATCH] Added querying array values --- gjson.go | 126 +++++++++++++++++++++++++++++++++++--------------- gjson_test.go | 22 +++++++++ 2 files changed, 111 insertions(+), 37 deletions(-) diff --git a/gjson.go b/gjson.go index 4b10d95..50c8e75 100644 --- a/gjson.go +++ b/gjson.go @@ -1215,6 +1215,53 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { c.pipe = rp.pipe c.piped = true } + + procQuery := func(qval Result) bool { + if rp.query.all { + if len(multires) == 0 { + multires = append(multires, '[') + } + } + var res Result + if qval.Type == JSON { + res = qval.Get(rp.query.path) + } else { + if rp.query.path != "" && rp.query.path != "_" { + return false + } + res = qval + } + if queryMatches(&rp, res) { + if rp.more { + left, right, ok := splitPossiblePipe(rp.path) + if ok { + rp.path = left + c.pipe = right + c.piped = true + } + res = qval.Get(rp.path) + } else { + res = qval + } + if rp.query.all { + raw := res.Raw + if len(raw) == 0 { + raw = res.String() + } + if raw != "" { + if len(multires) > 1 { + multires = append(multires, ',') + } + multires = append(multires, raw...) + } + } else { + c.value = res + return true + } + } + return false + } + for i < len(c.json)+1 { if !rp.arrch { pmatch = partidx == h @@ -1242,7 +1289,19 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { if !ok { return i, false } - if hit { + if rp.query.on { + var qval Result + if vesc { + qval.Str = unescape(val[1 : len(val)-1]) + } else { + qval.Str = val[1 : len(val)-1] + } + qval.Raw = val + qval.Type = String + if procQuery(qval) { + return i, true + } + } else if hit { if rp.alogok { break } @@ -1267,39 +1326,8 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { } else { i, val = parseSquash(c.json, i) if rp.query.on { - if rp.query.all { - if len(multires) == 0 { - multires = append(multires, '[') - } - } - res := Get(val, rp.query.path) - if queryMatches(&rp, res) { - if rp.more { - left, right, ok := splitPossiblePipe(rp.path) - if ok { - rp.path = left - c.pipe = right - c.piped = true - } - res = Get(val, rp.path) - } else { - res = Result{Raw: val, Type: JSON} - } - if rp.query.all { - raw := res.Raw - if len(raw) == 0 { - raw = res.String() - } - if raw != "" { - if len(multires) > 1 { - multires = append(multires, ',') - } - multires = append(multires, raw...) - } - } else { - c.value = res - return i, true - } + if procQuery(Result{Raw: val, Type: JSON}) { + return i, true } } else if hit { if rp.alogok { @@ -1321,7 +1349,11 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { } } else { i, val = parseSquash(c.json, i) - if hit { + if rp.query.on { + if procQuery(Result{Raw: val, Type: JSON}) { + return i, true + } + } else if hit { if rp.alogok { break } @@ -1332,7 +1364,15 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': i, val = parseNumber(c.json, i) - if hit { + if rp.query.on { + var qval Result + qval.Raw = val + qval.Type = Number + qval.Num, _ = strconv.ParseFloat(val, 64) + if procQuery(qval) { + return i, true + } + } else if hit { if rp.alogok { break } @@ -1344,7 +1384,19 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { case 't', 'f', 'n': vc := c.json[i] i, val = parseLiteral(c.json, i) - if hit { + if rp.query.on { + var qval Result + qval.Raw = val + switch vc { + case 't': + qval.Type = True + case 'f': + qval.Type = False + } + if procQuery(qval) { + return i, true + } + } else if hit { if rp.alogok { break } diff --git a/gjson_test.go b/gjson_test.go index dd51556..aa51d5c 100644 --- a/gjson_test.go +++ b/gjson_test.go @@ -1830,3 +1830,25 @@ func TestQueries(t *testing.T) { assert(t, Get(json, `i*.f*.#[cust2<=false].first`).Exists()) } + +func TestQueryArrayValues(t *testing.T) { + json := `{ + "artists": [ + ["Bob Dylan"], + "John Lennon", + "Mick Jagger", + "Elton John", + "Michael Jackson", + "John Smith", + true, + 123, + 456, + false, + null + ] + }` + assert(t, Get(json, `a*.#[0="Bob Dylan"]#|#`).String() == "1") + assert(t, Get(json, `a*.#[0="Bob Dylan 2"]#|#`).String() == "0") + assert(t, Get(json, `a*.#[%"John*"]#|#`).String() == "2") + assert(t, Get(json, `a*.#[="123"]#|#`).String() == "1") +}