Jq: Collapse object key values

Created on 14 Jul 2017  路  4Comments  路  Source: stedolan/jq

I've been working at this for a few days now, searching all over Google, Stackoverflow, and the JQ wiki... I want to collapse the nested keys "properties" and "type". Here's the input data from an Elasticsearch .kibana mapping :

{
  "dashboard": {
    "dynamic": "strict",
    "properties": {
      "description": {
        "type": "text"
      },
      "hits": {
        "type": "integer"
      },
      "kibanaSavedObjectMeta": {
        "properties": {
          "searchSourceJSON": {
            "type": "text"
          }
        }
      },
      "optionsJSON": {
        "type": "text"
      },
      "panelsJSON": {
        "type": "text"
      },
      "refreshInterval": {
        "properties": {
          "display": {
            "type": "keyword"
          },
          "pause": {
            "type": "boolean"
          },
          "section": {
            "type": "integer"
          },
          "value": {
            "type": "integer"
          }
        }
      },
      "timeFrom": {
        "type": "keyword"
      },
      "timeRestore": {
        "type": "boolean"
      },
      "timeTo": {
        "type": "keyword"
      },
      "title": {
        "type": "text"
      },
      "uiStateJSON": {
        "type": "text"
      },
      "version": {
        "type": "integer"
      }
    }
  }
}

desired output:

{
  "dashboard": {
    "description": "text",
    "hits": "integer",
    "kibanaSavedObjectMeta": {
      "searchSourceJSON": "text"
    },
    "optionsJSON": "text",
    "panelsJSON": "text",
    "refreshInterval": {
      "display": "keyword",
      "pause": "boolean",
      "section": "integer",
      "value": "integer"
    },
    "timeFrom": "keyword",
    "timeRestore": "boolean",
    "timeTo": "keyword",
    "title": "text",
    "uiStateJSON": "text",
    "version": "integer"
  }
}

Closest I've gotten:

cat file.json |  jq '.[] |= del(.dynamic)' | \
  jq '.. |= (if type == "object" and has("properties") then .properties else . end)' | \
  jq '.. |= (if type == "object" and has("type") then .type else . end)'

output:

jq: error (at <stdin>:112): Cannot index string with string "type"

Thanks for all the hard work! I've been using JQ for a few years now, and show it to everyone I can. :)

All 4 comments

Here is a solution:

def compact: with_entries( if .value.type then .value |= .type else . end);

walk( if type=="object" and has("properties") then .properties | compact else . end )

Once you understand with_entries and walk, it should be easy enough to adapt it to your needs.

For future reference, please ask usage questions at stackoverflow.com with the jq tag -- that way, others can more easily benefit from the Q & A. Thanks.

Will do. Thanks!

Ok, after compiling JQ from source under Ubuntu 14.04 Trusty LTS, to enable the "walk" function, I got my final answer with this:

cat file.json | \
  jq 'walk( if type=="object" and has("properties") then . |= .properties else . end )' | \
  jq 'walk( if type=="object" and has("type") then . |= .type else . end )'

For reference:

  1. If your jq does not have walk/1, you can simply add its definition (available e.g. at https://github.com/stedolan/jq/blob/master/src/builtin.jq)

  2. You can reduce the number of calls to top-level commands from 3 to 1, e.g. as follows:

    jq 'walk(...) | walk(...)' file.json

Was this page helpful?
0 / 5 - 0 ratings

Related issues

geoffeg picture geoffeg  路  3Comments

ghost picture ghost  路  4Comments

sloanlance picture sloanlance  路  3Comments

tbelaire picture tbelaire  路  4Comments

rubensayshi picture rubensayshi  路  3Comments