Skip to content

lafrenierejm/gron

 
 

Repository files navigation

gron

Make JSON and YAML greppable!

gron transforms JSON or YAML into discrete assignments to make it easier to grep for what you want and see the absolute "path" to it.

$ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=1" | fgrep "commit.author"
json[0].commit.author = {};
json[0].commit.author.date = "2016-07-02T10:51:21Z";
json[0].commit.author.email = "[email protected]";
json[0].commit.author.name = "Tom Hudson";

gron can work backwards too, enabling you to turn your filtered data back into JSON. To illustrate, add gron --ungron to the end of the above pipeline:

$ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=1" | fgrep "commit.author" | gron --ungron
[
  {
    "commit": {
      "author": {
        "date": "2016-07-02T10:51:21Z",
        "email": "[email protected]",
        "name": "Tom Hudson"
      }
    }
  }
]

Installation

gron has no runtime dependencies. You can just download a binary for Linux, Mac, Windows or FreeBSD and run it. Put the binary in your PATH (e.g. in /usr/local/bin) to make it easy to use:

tar xzf gron-linux-amd64-0.1.5.tgz
sudo mv gron /usr/local/bin/

Or if you're a Go user you can use go install:

go install github.com/tomnomnom/gron@latest

It's recommended that you alias ungron or norg (or both!) to gron --ungron. Put something like this in your shell profile (e.g. in ~/.bashrc):

alias norg="gron --ungron"
alias ungron="gron --ungron"

Or you could create a shell script in your PATH named ungron or norg to affect all users:

gron --ungron "$@"

Usage

gron supports reading JSON from three different input methods.
  1. Local file

    $ gron ./testdata/two.json
    json = {};
    json.contact = {};
    json.contact.email = "[email protected]";
    json.contact.twitter = "@TomNomNom";
    json.github = "https://github.com/tomnomnom/";
    json.likes = [];
    json.likes[0] = "code";
    json.likes[1] = "cheese";
    json.likes[2] = "meat";
    json.name = "Tom";
  2. URL

    $ gron http://headers.jsontest.com/
    json = {};
    json.Host = "headers.jsontest.com";
    json["User-Agent"] = "gron/0.1";
    json["X-Cloud-Trace-Context"] = "6917a823919477919dbc1523584ba25d/11970839830843610056";
  3. Standard input (stdin)

    $ curl -s http://headers.jsontest.com/ | gron
    json = {};
    json.Accept = "*/*";
    json.Host = "headers.jsontest.com";
    json["User-Agent"] = "curl/7.43.0";
    json["X-Cloud-Trace-Context"] = "c70f7bf26661c67d0b9f2cde6f295319/13941186890243645147";
Grep for something and easily see the path to it.
$ gron testdata/two.json | grep twitter
json.contact.twitter = "@TomNomNom";
Easily diff JSON.
$ diff <(gron two.json) <(gron two-b.json)
3c3
< json.contact.email = "[email protected]";
---
> json.contact.email = "[email protected]";
The output of gron is valid JavaScript.
$ gron ./testdata/two.json > tmp.js && echo "console.log(json);" >> tmp.js && nodejs tmp.js
{ contact: { email: '[email protected]', twitter: '@TomNomNom' },
  github: 'https://github.com/tomnomnom/',
  likes: [ 'code', 'cheese', 'meat' ],
  name: 'Tom' }
Obtain gron's output as a JSON stream via the --json switch.
$ curl -s http://headers.jsontest.com/ | gron --json
[[],{}]
[["Accept"],"*/*"]
[["Host"],"headers.jsontest.com"]
[["User-Agent"],"curl/7.43.0"]
[["X-Cloud-Trace-Context"],"c70f7bf26661c67d0b9f2cde6f295319/13941186890243645147"]

ungronning

gron can also turn its output back into JSON.
$ gron testdata/two.json | gron -u
{
  "contact": {
    "email": "[email protected]",
    "twitter": "@TomNomNom"
  },
  "github": "https://github.com/tomnomnom/",
  "likes": [
    "code",
    "cheese",
    "meat"
  ],
  "name": "Tom"
}
This means you use can use gron with grep and other tools to modify JSON.
$ gron testdata/two.json | grep likes | gron --ungron
{
  "likes": [
    "code",
    "cheese",
    "meat"
  ]
}
To preserve array keys, arrays are padded with null when values are missing.

To demonstrate, first create a shell pipeline that filters out an array entry:

$ gron testdata/two.json | grep likes | grep -v cheese
json.likes = [];
json.likes[0] = "code";
json.likes[2] = "meat";

Note that the array indices jump directly from 0 to 2 because we're excluding the "cheese" value via grep -v.

Now add gron --ungron to the end of the above pipeline to get JSON output:

$ gron testdata/two.json | grep likes | grep -v cheese | gron --ungron
{
  "likes": [
    "code",
    null,
    "meat"
  ]
}

Note the null placeholder has been inserted to account for the excluded "cheese" value.

If you get creative you can do some pretty neat tricks with gron, and then ungron the output back into JSON.

Get Help

Run gron --help for help:

gron transforms JSON or YAML (from a file, URL, or stdin) into discrete assignments to make it easier to grep for what you want and see the absolute "path" to it.

Examples:
  gron /tmp/apiresponse.json
  gron http://jsonplaceholder.typicode.com/users/1
  curl -s http://jsonplaceholder.typicode.com/users/1 | gron
  gron http://jsonplaceholder.typicode.com/users/1 | grep company | gron --ungron

Usage:
  gron [flags]

Flags:
  -c, --colorize     Colorize output (default on TTY)
  -h, --help         help for gron
  -k, --insecure     Disable certificate validation when reading from a URL
  -j, --json         Represent gron data as JSON stream
  -m, --monochrome   Do not colorize output
      --sort         Sort output
  -s, --stream       Treat each line of input as a separate JSON object
  -u, --ungron       Reverse the operation (turn assignments back into JSON)
  -v, --values       Print just the values of provided assignments
      --version      Print version information
  -y, --yaml         Treat input as YAML instead of JSON

FAQ

Wasn't this written in PHP before?

Yes it was! The original version is preserved here for posterity.

Why the change to Go?

Mostly to remove PHP as a dependency. There are a lot of people who work with JSON who don't have PHP installed.

Why shouldn't I just use jq?

jq is awesome, and a lot more powerful than gron, but with that power comes complexity. gron aims to make it easier to use the tools you already know, like grep and sed.

gron's primary purpose is to make it easy to find the path to a value in a deeply nested JSON blob when you don't already know the structure; much of jq's power is unlocked only once you know that structure.

About

Make JSON greppable!

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 88.2%
  • Nix 5.6%
  • Shell 3.1%
  • PHP 3.1%