---
name: "gron"
section: "1"
platform: "linux"
package: "gron"
version: "0.7.1-2+b8"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/gron"
---

# gron(1)

transform JSON into discrete, greppable assignments

## 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/⟩\\c .

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⟩\\c  for the Debian GNU/Linux system, but may be used by others

## SEE ALSO

**[grep(1)](/grep/1.md)**, **[ack(1)](/ack/1.md)**, **[ag(1)](/ag/1.md)**, **[rg(1)](/rg/1.md)**, **[jq(1)](/jq/1.md)**
