Compare commits

...

4 Commits

Author SHA1 Message Date
862cbc6b80 delete log rpv 2018-12-23 22:27:33 +08:00
013383b188 添加正则表达式的方法 2018-12-23 21:36:09 +08:00
fdedd9ddb2 改进正则的方法 2018-12-23 05:38:59 +08:00
8ca66dad60 改匹配模式为正则表达式 2018-12-23 05:04:37 +08:00
2 changed files with 92 additions and 30 deletions

109
gjson.go
View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -706,6 +707,8 @@ type arrayPathResult struct {
value string value string
all bool all bool
} }
re *regexp.Regexp
} }
func parseArrayPath(path string) (r arrayPathResult) { func parseArrayPath(path string) (r arrayPathResult) {
@ -741,6 +744,7 @@ func parseArrayPath(path string) (r arrayPathResult) {
path[i] == '<' || path[i] == '<' ||
path[i] == '>' || path[i] == '>' ||
path[i] == '%' || path[i] == '%' ||
path[i] == '~' ||
path[i] == ']' { path[i] == ']' {
break break
} }
@ -776,38 +780,66 @@ func parseArrayPath(path string) (r arrayPathResult) {
break break
} }
} }
s = i s = i + 1
for ; i < len(path); i++ {
if path[i] == '"' { if r.query.op == "~" {
i++ pair := path[i]
s2 := i i++
for ; i < len(path); i++ { GETREGEXPSTR:
if path[i] > '\\' { for ; i < len(path); i++ {
continue if path[i] == pair {
} for iend := i + 1; iend < len(path); iend++ {
if path[i] == '"' {
// look for an escaped slash if path[iend] == ' ' {
if path[i-1] == '\\' { continue
n := 0
for j := i - 2; j > s2-1; j-- {
if path[j] != '\\' {
break
}
n++
}
if n%2 == 0 {
continue
}
} }
break
if path[iend] == ']' {
if iend+1 < len(path) && path[iend+1] == '#' {
r.query.all = true
}
break GETREGEXPSTR
} else {
break
}
} }
} }
} else if path[i] == ']' {
if i+1 < len(path) && path[i+1] == '#' {
r.query.all = true
}
break
} }
} else {
for ; i < len(path); i++ {
if path[i] == '"' {
i++
s2 := i
for ; i < len(path); i++ {
if path[i] > '\\' {
continue
}
if path[i] == '"' {
// look for an escaped slash
if path[i-1] == '\\' {
n := 0
for j := i - 2; j > s2-1; j-- {
if path[j] != '\\' {
break
}
n++
}
if n%2 == 0 {
continue
}
}
break
}
}
} else if path[i] == ']' {
if i+1 < len(path) && path[i+1] == '#' {
r.query.all = true
}
break
}
} //
} }
if i > len(path) { if i > len(path) {
i = len(path) i = len(path)
@ -1077,6 +1109,22 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
} }
return i, false return i, false
} }
func escapeRegexpString(rpv string) string {
var content []byte
lrpv := len(rpv)
for i := 0; i < lrpv; i++ {
rpvChar := rpv[i]
if rpvChar == '\\' {
content = append(content, rpv[i+1])
i++
} else {
content = append(content, rpvChar)
}
}
return string(content)
}
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] == '"' { if len(rpv) > 2 && rpv[0] == '"' && rpv[len(rpv)-1] == '"' {
@ -1101,6 +1149,11 @@ func queryMatches(rp *arrayPathResult, value Result) bool {
return match.Match(value.Str, rpv) return match.Match(value.Str, rpv)
case "!%": case "!%":
return !match.Match(value.Str, rpv) return !match.Match(value.Str, rpv)
case "~":
if rp.re == nil {
rp.re = regexp.MustCompile(rpv)
}
return rp.re.MatchString(value.Str)
} }
case Number: case Number:
rpvn, _ := strconv.ParseFloat(rpv, 64) rpvn, _ := strconv.ParseFloat(rpv, 64)

View File

@ -390,6 +390,7 @@ func TestBasic1(t *testing.T) {
t.Fatalf("expected %v, got %v", 3, count) t.Fatalf("expected %v, got %v", 3, count)
} }
} }
func TestBasic2(t *testing.T) { func TestBasic2(t *testing.T) {
mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`) mtok := get(basicJSON, `loggy.programmers.#[age=101].firstName`)
if mtok.String() != "1002.3" { if mtok.String() != "1002.3" {
@ -399,14 +400,15 @@ func TestBasic2(t *testing.T) {
if mtok.String() != "Jason" { if mtok.String() != "Jason" {
t.Fatalf("expected %v, got %v", "Jason", mtok.String()) t.Fatalf("expected %v, got %v", "Jason", mtok.String())
} }
mtok = get(basicJSON, `loggy.programmers.#[firstName % "Bre*"].email`) mtok = get(basicJSON, `loggy.programmers.#[firstName % "Bre.*"].email`)
if mtok.String() != "aaaa" { if mtok.String() != "aaaa" {
t.Fatalf("expected %v, got %v", "aaaa", mtok.String()) t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
} }
mtok = get(basicJSON, `loggy.programmers.#[firstName !% "Bre*"].email`) mtok = get(basicJSON, `loggy.programmers.#[firstName !% "Bre.*"].email`)
if mtok.String() != "bbbb" { if mtok.String() != "bbbb" {
t.Fatalf("expected %v, got %v", "bbbb", mtok.String()) t.Fatalf("expected %v, got %v", "bbbb", mtok.String())
} }
mtok = get(basicJSON, `loggy.programmers.#[firstName == "Brett"].email`) mtok = get(basicJSON, `loggy.programmers.#[firstName == "Brett"].email`)
if mtok.String() != "aaaa" { if mtok.String() != "aaaa" {
t.Fatalf("expected %v, got %v", "aaaa", mtok.String()) t.Fatalf("expected %v, got %v", "aaaa", mtok.String())
@ -1431,3 +1433,10 @@ func TestArrayValues(t *testing.T) {
} }
} }
func TestEsonRegexp(t *testing.T) {
mtok := get(`{"data": [ {"dat": "123\"", "next": [{"a": "\"32"}, {"a": "32"}]}, {"dat": "234"} ] }`, `data.#[dat % "3\""].next.#[a % "\"32"]#.a`)
if mtok.String() != `["\"32"]` {
t.Fatalf("expected %v, got %v", `"32`, mtok.String())
}
}