mirror of https://github.com/tidwall/gjson.git
Added new static value character
You can use the '!' character to define static json as a path component. For example, {name.last,"foo":!"bar"} => {name.last,"foo":"bar"} see #249
This commit is contained in:
parent
2c9fd2476a
commit
6b6af2ad5e
68
gjson.go
68
gjson.go
|
@ -1807,7 +1807,7 @@ func isSimpleName(component string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
switch component[i] {
|
switch component[i] {
|
||||||
case '[', ']', '{', '}', '(', ')', '#', '|':
|
case '[', ']', '{', '}', '(', ')', '#', '|', '!':
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1871,23 +1871,25 @@ type parseContext struct {
|
||||||
// use the Valid function first.
|
// use the Valid function first.
|
||||||
func Get(json, path string) Result {
|
func Get(json, path string) Result {
|
||||||
if len(path) > 1 {
|
if len(path) > 1 {
|
||||||
if !DisableModifiers {
|
if (path[0] == '@' && !DisableModifiers) || path[0] == '!' {
|
||||||
if path[0] == '@' {
|
// possible modifier
|
||||||
// possible modifier
|
var ok bool
|
||||||
var ok bool
|
var npath string
|
||||||
var npath string
|
var rjson string
|
||||||
var rjson string
|
if path[0] == '@' && !DisableModifiers {
|
||||||
npath, rjson, ok = execModifier(json, path)
|
npath, rjson, ok = execModifier(json, path)
|
||||||
if ok {
|
} else if path[0] == '!' {
|
||||||
path = npath
|
npath, rjson, ok = execStatic(json, path)
|
||||||
if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
|
}
|
||||||
res := Get(rjson, path[1:])
|
if ok {
|
||||||
res.Index = 0
|
path = npath
|
||||||
res.Indexes = nil
|
if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
|
||||||
return res
|
res := Get(rjson, path[1:])
|
||||||
}
|
res.Index = 0
|
||||||
return Parse(rjson)
|
res.Indexes = nil
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
return Parse(rjson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if path[0] == '[' || path[0] == '{' {
|
if path[0] == '[' || path[0] == '{' {
|
||||||
|
@ -2556,8 +2558,40 @@ func safeInt(f float64) (n int64, ok bool) {
|
||||||
return int64(f), true
|
return int64(f), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execStatic parses the path to find a static value.
|
||||||
|
// The input expects that the path already starts with a '!'
|
||||||
|
func execStatic(json, path string) (pathOut, res string, ok bool) {
|
||||||
|
name := path[1:]
|
||||||
|
if len(name) > 0 {
|
||||||
|
switch name[0] {
|
||||||
|
case '{', '[', '"', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9':
|
||||||
|
_, res = parseSquash(name, 0)
|
||||||
|
pathOut = name[len(res):]
|
||||||
|
return pathOut, res, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 1; i < len(path); i++ {
|
||||||
|
if path[i] == '|' {
|
||||||
|
pathOut = path[i:]
|
||||||
|
name = path[1:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if path[i] == '.' {
|
||||||
|
pathOut = path[i:]
|
||||||
|
name = path[1:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch strings.ToLower(name) {
|
||||||
|
case "true", "false", "null", "nan", "inf":
|
||||||
|
return pathOut, name, true
|
||||||
|
}
|
||||||
|
return pathOut, res, false
|
||||||
|
}
|
||||||
|
|
||||||
// execModifier parses the path to find a matching modifier function.
|
// execModifier parses the path to find a matching modifier function.
|
||||||
// then input expects that the path already starts with a '@'
|
// The input expects that the path already starts with a '@'
|
||||||
func execModifier(json, path string) (pathOut, res string, ok bool) {
|
func execModifier(json, path string) (pathOut, res string, ok bool) {
|
||||||
name := path[1:]
|
name := path[1:]
|
||||||
var hasArgs bool
|
var hasArgs bool
|
||||||
|
|
|
@ -2410,3 +2410,31 @@ func TestQueryGetPath(t *testing.T) {
|
||||||
assert(t, arr[i].Path(readmeJSON) == fmt.Sprintf("friends.%d.first", i))
|
assert(t, arr[i].Path(readmeJSON) == fmt.Sprintf("friends.%d.first", i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStaticJSON(t *testing.T) {
|
||||||
|
json := `{
|
||||||
|
"name": {"first": "Tom", "last": "Anderson"}
|
||||||
|
}`
|
||||||
|
assert(t, Get(json,
|
||||||
|
`"bar"`).Raw ==
|
||||||
|
``)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`!"bar"`).Raw ==
|
||||||
|
`"bar"`)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`!{"name":{"first":"Tom"}}.{name.first}.first`).Raw ==
|
||||||
|
`"Tom"`)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`{name.last,"foo":!"bar"}`).Raw ==
|
||||||
|
`{"last":"Anderson","foo":"bar"}`)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`{name.last,"foo":!{"a":"b"},"that"}`).Raw ==
|
||||||
|
`{"last":"Anderson","foo":{"a":"b"}}`)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`{name.last,"foo":!{"c":"d"},!"that"}`).Raw ==
|
||||||
|
`{"last":"Anderson","foo":{"c":"d"},"_":"that"}`)
|
||||||
|
assert(t, Get(json,
|
||||||
|
`[!true,!false,!null,!inf,!nan,!hello,{"name":!"andy",name.last},+inf,!["any","thing"]]`).Raw ==
|
||||||
|
`[true,false,null,inf,nan,{"name":"andy","last":"Anderson"},["any","thing"]]`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue