Provided by: gron_0.7.1-1ubuntu0.23.10.1_amd64
NAME
gron - transform JSON into discrete, greppable assignments
SYNOPSIS
gron [OPTIONS] [FILE|URL] gron –-version gron –-help
DESCRIPTION
gron transforms JSON into discrete assignments to make it easier to grep for what you want and see the absolute `path' to it. It eases the exploration of APIs that return large blobs of JSON but have terrible documentation.
OPTIONS
-u, --ungron reverse the operation (turn assignments back into JSON) -v, --values print just the values of provided assignments -c, --colorize colorize output (default on tty) -m, --monochrome monochrome (don’t colorize output) -s, --stream treat each line of input as a separate JSON object -k, --insecure disable certificate validation -j, --json represent gron data as JSON stream --no-sort don’t sort output (faster) --version print version information
BASIC USAGE
Get JSON from a file: $ gron testdata/two.json json = {}; json.contact = {}; json.contact.email = "mail@tomnomnom.com"; 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"; From a 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"; Or from 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"; gron makes diffing JSON easy too: $ diff <(gron two.json) <(gron two-b.json) 3c3 < json.contact.email = "mail@tomnomnom.com"; --- > json.contact.email = "contact@tomnomnom.com"; The output of gron is valid JavaScript: $ gron testdata/two.json > tmp.js $ echo "console.log(json);" >> tmp.js $ nodejs tmp.js { contact: { email: 'mail@tomnomnom.com', twitter: '@TomNomNom' }, github: 'https://github.com/tomnomnom/', likes: [ 'code', 'cheese', 'meat' ], name: 'Tom' } It’s also possible to obtain the gron output as 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": "mail@tomnomnom.com", "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" ] } or $ gron --json testdata/two.json | grep likes | gron --json --ungron { "likes": [ "code", "cheese", "meat" ] } To preserve array keys, arrays are padded with null when values are missing: $ gron testdata/two.json | grep likes | grep -v cheese json.likes = []; json.likes[0] = "code"; json.likes[2] = "meat"; ▶ gron testdata/two.json | grep likes | grep -v cheese | gron --ungron { "likes": [ "code", null, "meat" ] }
ADVANCED USAGE
Although gron’s primary purpose is API discovery, when combined with other tools like grep it can do some interesting things. As an exercise, let’s try to mimic some of the examples from the jq tutorial (https://stedolan.github.io/jq/tutorial/). Disclaimer: munging data on the command line with gron can be useful, but using tools like grep and sed to manipulate the data is error-prone and shouldn’t be relied on in scripts. Get the last 5 commits from the gron repo: $ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=5" json = []; json[0] = {}; json[0].author = {}; json[0].author.avatar_url = "https://avatars.githubusercontent.com/u/58276?v=3"; json[0].author.events_url = "https://api.github.com/users/tomnomnom/events{/privacy}"; ... json[4].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/cbcad2299e55c28a9922776e58b2a0b5a0f05016"; json[4].parents[0].sha = "cbcad2299e55c28a9922776e58b2a0b5a0f05016"; json[4].parents[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/cbcad2299e55c28a9922776e58b2a0b5a0f05016"; json[4].sha = "91b204972e63a1166c9d148fbbfd839f8697f91b"; json[4].url = "https://api.github.com/repos/tomnomnom/gron/commits/91b204972e63a1166c9d148fbbfd839f8697f91b"; To make the rest of this a little more readable, let’s add an alias for that: $ alias ggh='gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=5"' Extract just the first commit using fgrep "json[0]": $ ggh | fgrep "json[0]" json[0] = {}; json[0].author = {}; json[0].author.avatar_url = "https://avatars.githubusercontent.com/u/58276?v=3"; json[0].author.events_url = "https://api.github.com/users/tomnomnom/events{/privacy}"; json[0].author.followers_url = "https://api.github.com/users/tomnomnom/followers"; ... json[0].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311"; json[0].parents[0].sha = "48aba5325ece087ae24ab72684851cbe77ce8311"; json[0].parents[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/48aba5325ece087ae24ab72684851cbe77ce8311"; json[0].sha = "7da81e29c27241c0a5c2e5d083ddebcfcc525908"; json[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/7da81e29c27241c0a5c2e5d083ddebcfcc525908"; Get just the committer’s name and the commit message using egrep "(committer.name|commit.message)": $ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" json[0].commit.committer.name = "Tom Hudson"; json[0].commit.message = "Adds 0.1.7 to changelog"; Turn the result back into JSON using gron --ungron: ▶ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | gron --ungron [ { "commit": { "committer": { "name": "Tom Hudson" }, "message": "Adds 0.1.7 to changelog" } } ] gron preserves the location of values in the JSON, but you can use sed to remove keys from the path: $ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g" json[0].name = "Tom Hudson"; json[0].message = "Adds 0.1.7 to changelog" With those keys removed, the result is a `flattened' object, which looks much cleaner when turned back into JSON with gron --ungron: $ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g" | gron --ungron [ { "message": "Adds 0.1.7 to changelog", "name": "Tom Hudson" } ] Removing the fgrep "json[0]" from the pipeline means we do the same for all commits: $ ggh | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g" | gron --ungron [ { "message": "Adds 0.1.7 to changelog", "name": "Tom Hudson" }, { "message": "Refactors natural sort to actually work + be more readable", "name": "Tom Hudson" }, ... To include the html_url key for each commit’s parents, all we need to do is add parents.*html_url into our call to egrep: $ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g" json[0].name = "Tom Hudson"; json[0].message = "Adds 0.1.7 to changelog"; json[0].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311"; json[1].name = "Tom Hudson"; json[1].message = "Refactors natural sort to actually work + be more readable"; json[1].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2"; ... To make the structure more like that in the final example in the jq tutorial, we can use sed -r "s/\.html_url//" to remove the .html_url part of the path: ▶ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g" | sed -r "s/\.html_url//" json[0].name = "Tom Hudson"; json[0].message = "Adds 0.1.7 to changelog"; json[0].parents[0] = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311"; json[1].name = "Tom Hudson"; json[1].message = "Refactors natural sort to actually work + be more readable"; json[1].parents[0] = "https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2"; ... And, of course, the statements can be turned back into JSON with gron --ungron: $ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g" | sed -r "s/\.html_url//" | gron --ungron [ { "message": "Adds 0.1.7 to changelog", "name": "Tom Hudson", "parents": [ "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311" ] }, { "message": "Refactors natural sort to actually work + be more readable", "name": "Tom Hudson", "parents": [ "https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2" ] }, ...
EXAMPLES
Read from a local file/network: $ gron /tmp/apiresponse.json $ gron http://jsonplaceholder.typicode.com/users/1 Retrieve remote JSON and pipe through gron: $ curl -s http://jsonplaceholder.typicode.com/users/1 | gron Flatten and filter JSON through gron, before turning result back into JSON: $ gron http://jsonplaceholder.typicode.com/users/1 | grep company | gron --ungron
TIPS
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 "$@” ```
EXIT STATUS
0 OK 1 Failed to open file 2 Failed to read input 3 Failed to form statements 4 Failed to fetch URL 5 Failed to parse statements 6 Failed to encode JSON
REPORTING BUGS
Upstream bug tracker: https://github.com/tomnomnom/gron/issues
COPYRIGHT
Copyright (c) 2016 Tom Hudson
AUTHOR
This manual page is based on the gron documentation. It was created by Nick Morrott <nickm@debian.org> for the Debian GNU/Linux system, but may be used by others
SEE ALSO
grep(1), ack(1), ag(1), rg(1), jq(1)