Skip to content

Commit 6ee9f87

Browse files
committed
Added Escape function
This commit adds the Escape function for escaping a path component, making it possible to directly querying keys that have special characters like dots. ``` json := `{ "user":{ "first.name": "Janet", "last.name": "Prichard" } }` user := gjson.Get(json, "user") println(user.Get(gjson.Escape("first.name")).String()) println(user.Get(gjson.Escape("last.name")).String()) // Output: // Janet // Prichard ``` See #333
1 parent be1bb7d commit 6ee9f87

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

gjson.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3410,7 +3410,7 @@ func (t Result) Path(json string) string {
34103410
if !rcomp.Exists() {
34113411
goto fail
34123412
}
3413-
comp := escapeComp(rcomp.String())
3413+
comp := Escape(rcomp.String())
34143414
path = append(path, '.')
34153415
path = append(path, comp...)
34163416
}
@@ -3425,17 +3425,31 @@ fail:
34253425
// isSafePathKeyChar returns true if the input character is safe for not
34263426
// needing escaping.
34273427
func isSafePathKeyChar(c byte) bool {
3428-
return c <= ' ' || c > '~' || c == '_' || c == '-' || c == ':' ||
3429-
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
3430-
(c >= '0' && c <= '9')
3428+
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
3429+
(c >= '0' && c <= '9') || c <= ' ' || c > '~' || c == '_' ||
3430+
c == '-' || c == ':'
34313431
}
34323432

3433-
// escapeComp escaped a path compontent, making it safe for generating a
3434-
// path for later use.
3435-
func escapeComp(comp string) string {
3433+
// Escape returns an escaped path component.
3434+
//
3435+
// json := `{
3436+
// "user":{
3437+
// "first.name": "Janet",
3438+
// "last.name": "Prichard"
3439+
// }
3440+
// }`
3441+
// user := gjson.Get(json, "user")
3442+
// println(user.Get(gjson.Escape("first.name"))
3443+
// println(user.Get(gjson.Escape("last.name"))
3444+
// // Output:
3445+
// // Janet
3446+
// // Prichard
3447+
func Escape(comp string) string {
34363448
for i := 0; i < len(comp); i++ {
34373449
if !isSafePathKeyChar(comp[i]) {
3438-
ncomp := []byte(comp[:i])
3450+
ncomp := make([]byte, len(comp)+1)
3451+
copy(ncomp, comp[:i])
3452+
ncomp = ncomp[:i]
34393453
for ; i < len(comp); i++ {
34403454
if !isSafePathKeyChar(comp[i]) {
34413455
ncomp = append(ncomp, '\\')

gjson_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,3 +2701,16 @@ func TestModDig(t *testing.T) {
27012701
assert(t, Get(json, "@dig:name").String() == `["melinda","jake"]`)
27022702
assert(t, Get(json, "@dig:secret").String() == `["password"]`)
27032703
}
2704+
2705+
func TestEscape(t *testing.T) {
2706+
json := `{
2707+
"user":{
2708+
"first.name": "Janet",
2709+
"last.name": "Prichard"
2710+
}
2711+
}`
2712+
user := Get(json, "user")
2713+
assert(t, user.Get(Escape("first.name")).String() == "Janet")
2714+
assert(t, user.Get(Escape("last.name")).String() == "Prichard")
2715+
assert(t, user.Get("first.name").String() == "")
2716+
}

0 commit comments

Comments
 (0)