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] and [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)

