From 7660d0f79f754f6f868e43311d8453126542687f Mon Sep 17 00:00:00 2001 From: tidwall Date: Thu, 27 Jun 2019 18:27:53 -0700 Subject: [PATCH] Allow for pipe and dot mixing --- gjson.go | 28 ++++++++++++++++++++++++---- gjson_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/gjson.go b/gjson.go index 4f91f4f..46b3029 100644 --- a/gjson.go +++ b/gjson.go @@ -866,9 +866,16 @@ func parseObjectPath(path string) (r objectPathResult) { } } if path[i] == '.' { + // peek at the next byte and see if it's a '@' modifier. r.part = path[:i] - r.path = path[i+1:] - r.more = true + if !DisableModifiers && !DisableChaining && + i < len(path)-1 && path[i+1] == '@' { + r.pipe = path[i+1:] + r.piped = true + } else { + r.path = path[i+1:] + r.more = true + } return } if path[i] == '*' || path[i] == '?' { @@ -892,7 +899,15 @@ func parseObjectPath(path string) (r objectPathResult) { continue } else if path[i] == '.' { r.part = string(epart) - r.path = path[i+1:] + // peek at the next byte and see if it's a '@' modifier + if !DisableModifiers && !DisableChaining && + i < len(path)-1 && path[i+1] == '@' { + r.pipe = path[i+1:] + r.piped = true + } else { + r.path = path[i+1:] + r.more = true + } r.more = true return } else if path[i] == '|' { @@ -1515,7 +1530,7 @@ func Get(json, path string) Result { var rjson string path, rjson, ok = execModifier(json, path) if ok { - if len(path) > 0 && path[0] == '|' { + if len(path) > 0 && (path[0] == '|' || path[0] == '.') { res := Get(rjson, path[1:]) res.Index = 0 return res @@ -2282,6 +2297,11 @@ func execModifier(json, path string) (pathOut, res string, ok bool) { break } } + if path[i] == '.' { + pathOut = path[i:] + name = path[1:i] + break + } } if fn, ok := modifiers[name]; ok { var args string diff --git a/gjson_test.go b/gjson_test.go index a092850..19d234d 100644 --- a/gjson_test.go +++ b/gjson_test.go @@ -1613,3 +1613,44 @@ func TestArrayEx(t *testing.T) { t.Fatalf("expected '%v', got '%v'", "2", res) } } + +func TestPipeDotMixing(t *testing.T) { + json := `{ + "info": { + "friends": [ + {"first": "Dale", "last": "Murphy", "age": 44}, + {"first": "Roger", "last": "Craig", "age": 68}, + {"first": "Jane", "last": "Murphy", "age": 47} + ] + } + }` + var res string + res = Get(json, `info.friends.#[first="Dale"].last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `info|friends.#[first="Dale"].last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `info|friends.#[first="Dale"]|last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `info|friends|#[first="Dale"]|last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `@ugly|info|friends|#[first="Dale"]|last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `@ugly|info.@ugly|friends|#[first="Dale"]|last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } + res = Get(json, `@ugly.info|@ugly.friends|#[first="Dale"]|last`).String() + if res != "Murphy" { + t.Fatalf("expected '%v', got '%v'", "Murphy", res) + } +}