diff --git a/docs/user-guide/jsonpath.md b/docs/user-guide/jsonpath.md index 3242127d35a..e0e507019d1 100644 --- a/docs/user-guide/jsonpath.md +++ b/docs/user-guide/jsonpath.md @@ -85,7 +85,6 @@ Given the input: Function | Description | Example | Result ---------|--------------------|--------------------|------------------ text | the plain text | kind is {.kind} | kind is List -"" | quote | {"{"} | { @ | the current object | {@} | the same as input . or [] | child operator | {.kind} or {['kind']}| List .. | recursive descent | {..name} | 127.0.0.1 127.0.0.2 myself e2e @@ -94,7 +93,7 @@ text | the plain text | kind is {.kind} | kind is List [,] | union operator | {.items[*]['metadata.name', 'status.capacity']} | 127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8] ?() | filter | {.users[?(@.name=="e2e")].user.password} | secret range, end | iterate list | {range .items[*]}[{.metadata.name}, {.status.capacity}] {end} | [127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] - +"" | quote interpreted string | {range .items[*]}{.metadata.name}{"\t"}{end} | 127.0.0.1 127.0.0.2 diff --git a/pkg/util/jsonpath/jsonpath.go b/pkg/util/jsonpath/jsonpath.go index f989948683a..005e21d013c 100644 --- a/pkg/util/jsonpath/jsonpath.go +++ b/pkg/util/jsonpath/jsonpath.go @@ -130,7 +130,7 @@ func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, erro case *ListNode: return j.evalList(value, node) case *TextNode: - return []reflect.Value{reflect.ValueOf(string(node.Text))}, nil + return []reflect.Value{reflect.ValueOf(node.Text)}, nil case *FieldNode: return j.evalField(value, node) case *ArrayNode: diff --git a/pkg/util/jsonpath/jsonpath_test.go b/pkg/util/jsonpath/jsonpath_test.go index 3345aee85b6..0817dcf7198 100644 --- a/pkg/util/jsonpath/jsonpath_test.go +++ b/pkg/util/jsonpath/jsonpath_test.go @@ -52,7 +52,7 @@ func testJSONPath(tests []jsonpathTest, t *testing.T) { } } -// testJSONPathSortOutput test testcases related to map, the results may print in random order +// testJSONPathSortOutput test cases related to map, the results may print in random order func testJSONPathSortOutput(tests []jsonpathTest, t *testing.T) { for _, test := range tests { j := New(test.name) @@ -66,7 +66,7 @@ func testJSONPathSortOutput(tests []jsonpathTest, t *testing.T) { t.Errorf("in %s, execute error %v", test.name, err) } out := buf.String() - //since map is itereated in random order, we need to sort the results. + //since map is visited in random order, we need to sort the results. sortedOut := strings.Fields(out) sort.Strings(sortedOut) sortedExpect := strings.Fields(test.expect) @@ -233,16 +233,17 @@ func TestKubernetes(t *testing.T) { } nodesTests := []jsonpathTest{ - {"range item", "{range .items[*]}{.metadata.name}, {end}{.kind}", nodesData, `127.0.0.1, 127.0.0.2, List`}, - {"range addresss", "{.items[*].status.addresses[*].address}", nodesData, - `127.0.0.1 127.0.0.2 127.0.0.3`}, - {"double range", "{range .items[*]}{range .status.addresses[*]}{.address}, {end}{end}", nodesData, - `127.0.0.1, 127.0.0.2, 127.0.0.3, `}, - {"item name", "{.items[*].metadata.name}", nodesData, `127.0.0.1 127.0.0.2`}, - {"union nodes capacity", "{.items[*]['metadata.name', 'status.capacity']}", nodesData, - `127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]`}, - {"range nodes capacity", "{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}", nodesData, - `[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] `}, + {"range item", `{range .items[*]}{.metadata.name}, {end}{.kind}`, nodesData, "127.0.0.1, 127.0.0.2, List"}, + {"range item with quote", `{range .items[*]}{.metadata.name}{"\t"}{end}`, nodesData, "127.0.0.1\t127.0.0.2\t"}, + {"range addresss", `{.items[*].status.addresses[*].address}`, nodesData, + "127.0.0.1 127.0.0.2 127.0.0.3"}, + {"double range", `{range .items[*]}{range .status.addresses[*]}{.address}, {end}{end}`, nodesData, + "127.0.0.1, 127.0.0.2, 127.0.0.3, "}, + {"item name", `{.items[*].metadata.name}`, nodesData, "127.0.0.1 127.0.0.2"}, + {"union nodes capacity", `{.items[*]['metadata.name', 'status.capacity']}`, nodesData, + "127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]"}, + {"range nodes capacity", `{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}`, nodesData, + "[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] "}, {"user password", `{.users[?(@.name=="e2e")].user.password}`, &nodesData, "secret"}, } testJSONPath(nodesTests, t) diff --git a/pkg/util/jsonpath/node.go b/pkg/util/jsonpath/node.go index bdbf0d38d22..9d5242de7bf 100644 --- a/pkg/util/jsonpath/node.go +++ b/pkg/util/jsonpath/node.go @@ -84,11 +84,11 @@ func (l *ListNode) String() string { // TextNode holds plain text. type TextNode struct { NodeType - Text []byte // The text; may span newlines. + Text string // The text; may span newlines. } func newText(text string) *TextNode { - return &TextNode{NodeType: NodeText, Text: []byte(text)} + return &TextNode{NodeType: NodeText, Text: text} } func (t *TextNode) String() string { diff --git a/pkg/util/jsonpath/parser.go b/pkg/util/jsonpath/parser.go index facc4834d60..bd1f5ecd435 100644 --- a/pkg/util/jsonpath/parser.go +++ b/pkg/util/jsonpath/parser.go @@ -359,7 +359,7 @@ Loop: return p.parseInsideAction(cur) } -// parseQuote scans array index selection +// parseQuote unquotes string inside double quote func (p *Parser) parseQuote(cur *ListNode) error { Loop: for { @@ -371,7 +371,11 @@ Loop: } } value := p.consumeText() - cur.append(newText(value[1 : len(value)-1])) + s, err := strconv.Unquote(value) + if err != nil { + return fmt.Errorf("unquote string %s error %v", value, err) + } + cur.append(newText(s)) return p.parseInsideAction(cur) }