JGrep
... is a command line tool and API for parsing JSON documents based on logical expressions.
Installation:
jgrep is available as a gem:
gem install jgrep
JGrep binary usage
jgrep [expression] -i foo.json
or
cat "foo.json" | jgrep [expression]
Flags
-s, --simple [FIELDS] : Greps the JSON and only returns the value of the field(s) specified
-c, --compat : Returns the JSON in its non-pretty flat form
-n, --stream : Specify continuous input
-f, --flatten : Flatten the results as much as possible
-i, --input [FILENAME] : Target JSON file to use as input
-q, --quiet : Quiet; don't write to stdout. Exit with zero status if match found.
-v, --verbose : Verbose output that will list a document if it fails to parse
--start FIELD : Starts the grep at a specific key in the document
--slice [RANGE] : A range of the form 'n' or 'n..m', indicating which documents to extract from the final output
Expressions
JGrep uses the following logical symbols to define expressions.
'and' :
- [statement] and [statement]
Evaluates to true if both statements are true
'or' :
- [statement] or [statement]
Evaluates true if either statement is true
'not' :
- ! [statement]
- not [statement]
Inverts the value of statement
'+'
- +[value]
Returns true if value is present in the json document
'-'
- -[value]
Returns true if value is not present in the json doument
'(' and ')'
- (expression1) and expression2
Performs the operations inside the perentheses first.
Statements
A statement is defined as some value in a json document compared to another value. Available comparison operators are '=', '<', '>', '<=', '>='
Examples:
foo.bar=1
foo.bar>0
foo.bar<=1.3
Complex expressions
Given a json document, {"foo":1, "bar":null}, the following are examples of valid expressions
Examples:
+foo
... returns true
-bar
... returns false
+foo and !(foo=2)
... returns true
!(foo>=2 and bar=null) or !(bar=null)
... returns true
CLI missing an expression
If JGrep is executed without a set expression, it will return an unmodified JSON document. The -s flag can still be applied to the result.
In document comparison
If a document contains an array, the '[' and ']' operators can be used to define a comparison where statements are checked for truth on a per element basis which will then be combined.
Example:
[foo.bar1=1 and foo.bar2=2]
on
[
{
"foo": [
{
"bar1":1
},
{
"bar2":2
}
]
},
{
"foo": [
{
"bar1":0
},
{
"bar2":0
}
]
}
]
will return
[
{
"foo": [
{
"bar1": 1
},
{
"bar2": 2
}
]
}
]
Note: In document comparison cannot be nested.
The -s flag
The s flag simplifies the output returned by JGrep. Given a JSON document
[{"a":1, "b":2, "c":3}, {"a":3, "b":2, "c":1}]
a JGrep invocation like
cat my.json | jgrep "a=1" -s b
will output
1
The s flag can also be used with multiple field, which will return JSON as output which only contain the specified fields. Note: Separate fields by a space and enclose all fields in quotes (see example below)
Given:
[{"a":1, "b":2, "c":3}, {"a":3, "b":2, "c":1}]
a JGrep invocation like
cat my.json | jgrep "a>0" -s "a c"
will output
[
{
"a" : 1,
"c" : 3
},
{
"a" : 3,
"c" : 1
}
]
The --start flag
Some documents do not comply to our expected format, they might have an array embedded deep in a field. The --start flag lets you pick a starting point for the grep.
An example document can be seen here:
{"results": [
{"name":"Jack", "surname":"Smith"},
{"name":"Jill", "surname":"Jones"}
]
}
This document does not comply to our standard but does contain data that can be searched - the results field. We can use the --start flat to tell jgrep to start looking for data in that field:
$ cat my.json | jgrep --start results name=Jack -s surname Smith
The --slice flag
Allows the user to provide an int or range to slice an array of results with, in particular so a single element can be extracted, e.g.
$ echo '[{"foo": {"bar": "baz"}}, {"foo": {"bar":"baz"}}]' |
jgrep "foo.bar=baz" --slice 0
{
"foo": {
"bar": "baz"
}
}
The --stream flag
With the --stream or -n flag, jgrep will process multiple JSON inputs (newline separated) until standard input is closed. Each JSON input will be processed as usual, but the output immediately printed.
JGrep Gem usage
require 'jgrep'
json = File.read("yourfile.json")
expression = "foo=1 or bar=1"
JGrep::jgrep(json, expression)
sflags = "foo"
JGrep::jgrep(json, expression, sflags)
Transfer Notice
This project was originally authored by Pieter Loubser. The maintainer preferred that Vox Pupuli take ownership of the project for future improvement and maintenance. Existing pull requests and issues were transferred over, please fork and continue to contribute here instead of ploubser/JSON-Grep.