2016-06-07 09:07:55 +00:00
|
|
|
# gron
|
2016-06-04 21:58:04 +00:00
|
|
|
[![Build Status](https://travis-ci.org/tomnomnom/gron.svg?branch=master)](https://travis-ci.org/tomnomnom/gron)
|
2012-09-08 00:47:58 +00:00
|
|
|
|
2016-06-02 22:46:01 +00:00
|
|
|
Make JSON greppable!
|
2012-09-08 00:47:58 +00:00
|
|
|
|
2016-06-07 09:07:55 +00:00
|
|
|
gron transforms JSON into discrete assignments to make it easier to `grep` for what you want and see the absolute 'path' to it.
|
2016-06-02 22:46:01 +00:00
|
|
|
It eases the exploration of APIs that return large blobs of JSON but have terrible documentation.
|
2012-09-08 00:47:58 +00:00
|
|
|
|
2016-06-30 23:39:13 +00:00
|
|
|
<pre>
|
2016-07-02 11:04:56 +00:00
|
|
|
▶ <b>gron</b> '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 = "mail@tomnomnom.com";
|
|
|
|
json[0].commit.author.name = "Tom Hudson";
|
2016-07-02 10:50:29 +00:00
|
|
|
</pre>
|
2016-07-02 11:04:56 +00:00
|
|
|
|
|
|
|
gron can work backwards too, enabling you to turn your filtered data back into JSON:
|
2016-07-02 10:50:29 +00:00
|
|
|
<pre>
|
2016-07-02 11:04:56 +00:00
|
|
|
▶ gron 'https://api.github.com/repos/tomnomnom/gron/commits?per_page=1' | fgrep 'commit.author' | <b>gron --ungron</b>
|
|
|
|
[
|
|
|
|
{
|
|
|
|
"commit": {
|
|
|
|
"author": {
|
|
|
|
"date": "2016-07-02T10:51:21Z",
|
|
|
|
"email": "mail@tomnomnom.com",
|
|
|
|
"name": "Tom Hudson"
|
|
|
|
}
|
2016-07-02 10:49:46 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-02 11:04:56 +00:00
|
|
|
]
|
2016-06-30 23:39:13 +00:00
|
|
|
</pre>
|
|
|
|
|
2016-07-02 11:04:56 +00:00
|
|
|
> Disclaimer: the GitHub API documentation is fantastic, but it makes for a good example.
|
|
|
|
|
2016-06-07 09:17:01 +00:00
|
|
|
## Installation
|
|
|
|
|
2016-07-02 23:24:52 +00:00
|
|
|
gron has no runtime dependencies. You can just [download a binary for Linux, Mac or Windows and run it](https://github.com/tomnomnom/gron/releases).
|
2016-06-07 09:17:01 +00:00
|
|
|
Put the binary in your `$PATH` (e.g. in `/usr/bin`) to make it easy to use:
|
|
|
|
```
|
|
|
|
▶ tar xzf gron-linux-amd64-0.1.5.tgz
|
|
|
|
▶ sudo mv gron /usr/bin/
|
|
|
|
```
|
|
|
|
|
|
|
|
Or if you're a Go user you can use `go get`:
|
|
|
|
|
|
|
|
```
|
2016-06-19 22:45:34 +00:00
|
|
|
▶ go get -u github.com/tomnomnom/gron
|
2016-06-07 09:17:01 +00:00
|
|
|
```
|
2016-06-07 09:07:55 +00:00
|
|
|
|
2016-06-30 22:48:44 +00:00
|
|
|
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"
|
|
|
|
```
|
|
|
|
|
2012-09-08 00:47:58 +00:00
|
|
|
## Usage
|
|
|
|
|
2016-06-04 12:41:31 +00:00
|
|
|
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";
|
|
|
|
```
|
|
|
|
|
2016-06-05 20:06:12 +00:00
|
|
|
From a URL:
|
|
|
|
|
|
|
|
```
|
|
|
|
▶ gron http://headers.jsontest.com/
|
|
|
|
json = {};
|
|
|
|
json.Host = "headers.jsontest.com";
|
2016-06-19 22:45:34 +00:00
|
|
|
json["User-Agent"] = "gron/0.1";
|
2016-06-05 20:06:12 +00:00
|
|
|
json["X-Cloud-Trace-Context"] = "6917a823919477919dbc1523584ba25d/11970839830843610056";
|
|
|
|
```
|
|
|
|
|
2016-06-04 12:41:31 +00:00
|
|
|
Or from `stdin`:
|
|
|
|
|
2016-06-02 22:46:01 +00:00
|
|
|
```
|
2016-06-04 12:41:31 +00:00
|
|
|
▶ curl -s http://headers.jsontest.com/ | gron
|
2016-06-02 22:46:01 +00:00
|
|
|
json = {};
|
2016-06-04 12:41:31 +00:00
|
|
|
json.Accept = "*/*";
|
|
|
|
json.Host = "headers.jsontest.com";
|
|
|
|
json["User-Agent"] = "curl/7.43.0";
|
|
|
|
json["X-Cloud-Trace-Context"] = "c70f7bf26661c67d0b9f2cde6f295319/13941186890243645147";
|
2016-06-02 22:46:01 +00:00
|
|
|
```
|
|
|
|
|
2016-06-04 12:42:56 +00:00
|
|
|
Grep for something and easily see the path to it:
|
2016-06-02 22:46:01 +00:00
|
|
|
|
|
|
|
```
|
2016-06-04 12:41:31 +00:00
|
|
|
▶ gron testdata/two.json | grep twitter
|
|
|
|
json.contact.twitter = "@TomNomNom";
|
2016-06-02 22:46:01 +00:00
|
|
|
```
|
2012-09-08 00:47:58 +00:00
|
|
|
|
2016-06-05 12:40:24 +00:00
|
|
|
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' }
|
|
|
|
```
|
|
|
|
|
2016-06-30 20:02:42 +00:00
|
|
|
## 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"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2016-06-30 20:05:27 +00:00
|
|
|
This means you use can use gron with `grep` and other tools to modify JSON:
|
2016-06-30 20:02:42 +00:00
|
|
|
```
|
|
|
|
▶ 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:
|
|
|
|
```
|
|
|
|
▶ 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"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2016-06-30 22:35:49 +00:00
|
|
|
If you get creative you can do [some pretty neat tricks with gron](ADVANCED.mkd), and
|
|
|
|
then ungron the output back into JSON.
|
2016-06-30 20:05:27 +00:00
|
|
|
|
2016-06-05 20:47:23 +00:00
|
|
|
## Get Help
|
2016-06-04 12:41:31 +00:00
|
|
|
|
|
|
|
```
|
2016-06-04 12:44:06 +00:00
|
|
|
▶ gron --help
|
2016-06-05 20:06:12 +00:00
|
|
|
Transform JSON (from a file, URL, or stdin) into discrete assignments to make it greppable
|
2016-06-04 12:41:31 +00:00
|
|
|
|
|
|
|
Usage:
|
2016-06-30 20:02:42 +00:00
|
|
|
gron [OPTIONS] [FILE|URL|-]
|
|
|
|
|
|
|
|
Options:
|
|
|
|
-u, --ungron Reverse the operation (turn assignments back into JSON)
|
2016-06-04 12:41:31 +00:00
|
|
|
|
|
|
|
Exit Codes:
|
2016-06-05 20:06:12 +00:00
|
|
|
0 OK
|
|
|
|
1 Failed to open file
|
|
|
|
2 Failed to read input
|
|
|
|
3 Failed to decode JSON
|
2016-06-30 20:02:42 +00:00
|
|
|
4 Failed to form statements
|
2016-06-05 20:06:12 +00:00
|
|
|
5 Failed to fetch URL
|
2016-06-30 20:02:42 +00:00
|
|
|
6 Failed to parse statements
|
|
|
|
7 Failed to encode JSON
|
2016-06-04 12:41:31 +00:00
|
|
|
|
|
|
|
Examples:
|
|
|
|
gron /tmp/apiresponse.json
|
2016-06-30 20:02:42 +00:00
|
|
|
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
|
2016-06-04 12:41:31 +00:00
|
|
|
```
|
2016-06-04 17:54:32 +00:00
|
|
|
|
2016-06-07 09:07:55 +00:00
|
|
|
## FAQ
|
|
|
|
### Wasn't this written in PHP before?
|
|
|
|
Yes it was! The original version is [preserved here for posterity](https://github.com/tomnomnom/gron/blob/master/original-gron.php).
|
2016-06-04 17:54:32 +00:00
|
|
|
|
2016-06-07 09:07:55 +00:00
|
|
|
### Why the change to Go?
|
|
|
|
Mostly to remove PHP as a dependency. There's a lot of people who work with JSON who don't have PHP installed.
|
2016-06-04 22:05:36 +00:00
|
|
|
|
2016-06-07 09:07:55 +00:00
|
|
|
### Why shouldn't I just use jq?
|
|
|
|
[jq](https://stedolan.github.io/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`.
|
2016-06-04 22:05:36 +00:00
|
|
|
|
2016-06-07 09:07:55 +00:00
|
|
|
gron's primary purpose is to make it easy to find the path to a value in a deeply nested JSON blob
|
2016-06-07 09:11:07 +00:00
|
|
|
when you don't already know the structure; much of jq's power is unlocked only once you know that structure.
|