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. :)
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:
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)
You can reduce the number of calls to top-level commands from 3 to 1, e.g. as follows:
jq 'walk(...) | walk(...)' file.json