34

I've got JSON that looks like this

{
  "keyword1": {
    "identifier1": 16
  },
  "keyword2": {
    "identifier2": 16
  }
}

and I need to loop through the keywords to get the identifiers (not sure if I'm using the right terminology here). Seems pretty simple, but because the keywords are all named different, I don't know how to handle that.

peak
  • 105,803
  • 17
  • 152
  • 177
Adam vonNieda
  • 1,635
  • 2
  • 14
  • 22

4 Answers4

51

The original tag for this question was jq so here is a jq solution:

.[] | keys[]

For example, with the input as shown in the question:

$ jq '.[] | keys[]' input.json

"identifier1"
"identifier2"

To retrieve the key names in the order they appear in the JSON object, use keys_unsorted.

peak
  • 105,803
  • 17
  • 152
  • 177
27

I'd think something along these lines would work well:

jq '. | to_entries | .[].key'

see https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries

or if you wanted to get the values from a variable:

JSON_DATA={main:{k1:v1,k2:v2}}
result=$(jq -n "$JSON_DATA" | jq '.main | to_entries | .[].value' --raw-output)
echo $result

##outputs: v1 v2
bristweb
  • 948
  • 14
  • 14
5

I came here hoping to sort out a bunch of keys from my JSON, I found two features handy. There are three functions "to_entries", "from_entries", and "with_entries". You can filter the values by key or value, like so:

JSON_DATA='
{
  "fields": {
    "first": null,
    "second": "two",
    "third": "three"
  }
}
'

echo "$JSON_DATA" | jq '{fields: .fields | with_entries(select(.value != null and .key != "third")) }'

Output:

{
  "fields": {
    "second": "two"
  }
}
turiyag
  • 2,757
  • 2
  • 22
  • 21
1

simpler solution - just treat internal hash as a new hash and add one more filter. The query that helped me:

$ docker network inspect bridge|jq '.[].Containers'
{
  "35c9e1273c43db01c45b5f43f6999d04c18beff3996ea09fb8b87a8b635c38ff": {
    "Name": "nginx",
    "EndpointID": "a6e788d6f90eb14df2321a2eb02517f0862c1fe7fe50c02f2b8c103c0c79cb6b",
    "MacAddress": "02:42:ac:11:00:02",
    "IPv4Address": "172.17.0.2/16",
    "IPv6Address": ""
  },
  "b46c157cec243969f9227251dfd6fa65b7a904e145df80a63f79d4dc8b281355": {
    "Name": "sweet_gates",
    "EndpointID": "a600d9c1ee35b9f7db31249ae8f589c202e0b260e10a394757a88bfd66b5b42f",
    "MacAddress": "02:42:ac:11:00:03",
    "IPv4Address": "172.17.0.3/16",
    "IPv6Address": ""
  }
}

As I needed only couple of fields, add to above .json one more query:

$ docker network inspect bridge|jq -jr '.[].Containers[]|.IPv4Address, "\t", .Name, "\n"'
172.17.0.2/16   nginx
172.17.0.3/16   sweet_gates