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
44
gjson.go
44
gjson.go
|
@ -1807,7 +1807,7 @@ func isSimpleName(component string) bool {
|
|||
return false
|
||||
}
|
||||
switch component[i] {
|
||||
case '[', ']', '{', '}', '(', ')', '#', '|':
|
||||
case '[', ']', '{', '}', '(', ')', '#', '|', '!':
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -1871,13 +1871,16 @@ type parseContext struct {
|
|||
// use the Valid function first.
|
||||
func Get(json, path string) Result {
|
||||
if len(path) > 1 {
|
||||
if !DisableModifiers {
|
||||
if path[0] == '@' {
|
||||
if (path[0] == '@' && !DisableModifiers) || path[0] == '!' {
|
||||
// possible modifier
|
||||
var ok bool
|
||||
var npath string
|
||||
var rjson string
|
||||
if path[0] == '@' && !DisableModifiers {
|
||||
npath, rjson, ok = execModifier(json, path)
|
||||
} else if path[0] == '!' {
|
||||
npath, rjson, ok = execStatic(json, path)
|
||||
}
|
||||
if ok {
|
||||
path = npath
|
||||
if len(path) > 0 && (path[0] == '|' || path[0] == '.') {
|
||||
|
@ -1889,7 +1892,6 @@ func Get(json, path string) Result {
|
|||
return Parse(rjson)
|
||||
}
|
||||
}
|
||||
}
|
||||
if path[0] == '[' || path[0] == '{' {
|
||||
// using a subselector path
|
||||
kind := path[0]
|
||||
|
@ -2556,8 +2558,40 @@ func safeInt(f float64) (n int64, ok bool) {
|
|||
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.
|
||||
// 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) {
|
||||
name := path[1:]
|
||||
var hasArgs bool
|
||||
|
|
|
@ -2410,3 +2410,31 @@ func TestQueryGetPath(t *testing.T) {
|
|||
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