How to sort a json file by keys and values of those keys in jq

karlos picture karlos · May 19, 2015 · Viewed 45.8k times · Source

We're building a website using the Pentaho CTools library, which has a graphical dashboard editor which writes out JSON-format files for part of the dashboard.

I'd like to apply a transform to these files before check-in to git in order to sort them by key and then by the value of certain keys. The purpose is to make diffs easier, since the editor has a habit of rearranging all of the json fields.

For example, we might have something like this:

{
  "components": {
    "rows": [
      {
        "id": "CHARTS",
        "name": "Charts",
        "parent": "UnIqEiD",
        "properties": [
          {
            "name": "Group",
            "type": "Label",
            "value": "Charts"
          }
        ],
        "type": "Label",
        "typeDesc": "<i>Group</i>"
      },
      {
        "id": "kjalajsdjf",
        "meta_cdwSupport": "true",
        "parent": "CHARTS",
        "properties": [
          {
            "name": "name",
            "type": "Id",
            "value": "Value1"
          },
          {
            "name": "title",
            "type": "String",
            "value": "Value2"
          },
          {
            "name": "listeners",
            "type": "Listeners",
            "value": "[]"
          },
...

We are able to jq --sort-keys (http://stedolan.github.io/jq/) to sort all of the keys, but I'm struggling to find out how to use the sort_by function to then sort certain specific elements by the value of certain keys (so, in the example above, sorting by properties.name for example. Any ideas?

Answer

karlos picture karlos · May 19, 2015

Ok with some assistance on the IRC channel I've found an answer.

Basically, it looks like this:

jq '.components.rows|=sort_by(.id)|.components.rows[].properties|=sort_by(.name)' file.json > out.json

So you do the select of the right object, walking into arrays if needed, and then sort_by just takes a single value. I was trying sort_by(.components.rows.id) which failed.

The |= instead of the | passes the values along instead of stripping them.