Skip to content

Commit ca51577

Browse files
James Haggertysuntong
authored andcommitted
Allow processing of a stream of separate JSON elements
See jmespath#11
1 parent e35e9a0 commit ca51577

File tree

2 files changed

+45
-22
lines changed

2 files changed

+45
-22
lines changed

jp.go

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6+
"io"
67
"io/ioutil"
78
"os"
89

@@ -33,6 +34,10 @@ func main() {
3334
Usage: "If the final result is a string, it will be printed without quotes.",
3435
EnvVar: "JP_UNQUOTED",
3536
},
37+
cli.BoolFlag{
38+
Name: "stream, s",
39+
Usage: "Parse JSON elements until the input stream is exhausted (rather than just the first).",
40+
},
3641
cli.BoolFlag{
3742
Name: "ast",
3843
Usage: "Only print the AST of the parsed expression. Do not rely on this output, only useful for debugging purposes.",
@@ -82,7 +87,6 @@ func runMain(c *cli.Context) int {
8287
fmt.Printf("%s\n", parsed)
8388
return 0
8489
}
85-
var input interface{}
8690
var jsonParser *json.Decoder
8791
if c.String("filename") != "" {
8892
f, err := os.Open(c.String("filename"))
@@ -94,30 +98,38 @@ func runMain(c *cli.Context) int {
9498
} else {
9599
jsonParser = json.NewDecoder(os.Stdin)
96100
}
97-
if err := jsonParser.Decode(&input); err != nil {
98-
errMsg("Error parsing input json: %s\n", err)
99-
return 2
100-
}
101-
result, err := jmespath.Search(expression, input)
102-
if err != nil {
103-
if syntaxError, ok := err.(jmespath.SyntaxError); ok {
104-
return errMsg("%s\n%s\n",
105-
syntaxError,
106-
syntaxError.HighlightLocation())
101+
for {
102+
var input interface{}
103+
if err := jsonParser.Decode(&input); err == io.EOF {
104+
break
105+
} else if err != nil {
106+
errMsg("Error parsing input json: %s\n", err)
107+
return 2
107108
}
108-
return errMsg("Error evaluating JMESPath expression: %s", err)
109-
}
110-
converted, isString := result.(string)
111-
if c.Bool("unquoted") && isString {
112-
os.Stdout.WriteString(converted)
113-
} else {
114-
toJSON, err := json.MarshalIndent(result, "", " ")
109+
result, err := jmespath.Search(expression, input)
115110
if err != nil {
116-
errMsg("Error marshalling result to JSON: %s\n", err)
117-
return 3
111+
if syntaxError, ok := err.(jmespath.SyntaxError); ok {
112+
return errMsg("%s\n%s\n",
113+
syntaxError,
114+
syntaxError.HighlightLocation())
115+
}
116+
return errMsg("Error evaluating JMESPath expression: %s", err)
117+
}
118+
converted, isString := result.(string)
119+
if c.Bool("unquoted") && isString {
120+
os.Stdout.WriteString(converted)
121+
} else {
122+
toJSON, err := json.MarshalIndent(result, "", " ")
123+
if err != nil {
124+
errMsg("Error marshalling result to JSON: %s\n", err)
125+
return 3
126+
}
127+
os.Stdout.Write(toJSON)
128+
}
129+
os.Stdout.WriteString("\n")
130+
if !c.Bool("stream") {
131+
break
118132
}
119-
os.Stdout.Write(toJSON)
120133
}
121-
os.Stdout.WriteString("\n")
122134
return 0
123135
}

test/cases/search.bats

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
[ "$output" == "\"bar\"" ]
1515
}
1616

17+
@test "Ignores subsequent data" {
18+
output=$(echo '{"foo": "bar"}blah' | ./jp foo)
19+
[ "$output" == "\"bar\"" ]
20+
}
21+
22+
@test "Processes subsequent data in stream mode" {
23+
output=$(echo '{"foo": "bar"}{"foo": "x"}' | ./jp -s foo)
24+
echo "$output"
25+
[ "$output" == $'\"bar\"\n\"x\"' ]
26+
}
27+
1728
@test "Can search subexpr expression" {
1829
output=$(echo '{"foo": {"bar": "baz"}}' | ./jp foo.bar)
1930
[ "$output" == "\"baz\"" ]

0 commit comments

Comments
 (0)