DEV Community

Josh Branchaud
Josh Branchaud

Posted on • Edited on

Reduce a JSON Object to just Entries of a Specific Type with jq

A large JSON object can be hard to work with when it has tons of top-level fields that you have to wade through. One way to make that data exploration more approachable is to reduce what is there — filtering by type is a great starting point. Here is how I do that with the jq utility.

Let's say I want to start with a view of the JSON that is restricted to just the field whose values are of type array.

To do this, I need to use a couple different jq helper functions.

The select function produces the input value as the output if the given boolean expression is true. This is where I can do the type check. In this case, does the type of .value match "array".

select(.value | type | match("array"))
Enter fullscreen mode Exit fullscreen mode

Combining that select with map, I can filter an array to just those values that match my condition.

map(select(.value | type | match("array")))
Enter fullscreen mode Exit fullscreen mode

Because map expects an array and I'm starting with an object, I need to open up with a to_entries call. This turns the object into an array of .key and .value pairs. Hence, the .value that appears inside the select. Putting a from_entries on the other end of the map will take the reduced array of key-value pairs and turn it back into an object.

some_obj | to_entries | map(...) | from_entries
Enter fullscreen mode Exit fullscreen mode

Putting this all together:

jq '. | to_entries | map(select(.value | type | match("array"))) | from_entries' data.json
Enter fullscreen mode Exit fullscreen mode

There is a less verbose way to do the above. The to_entries and from_entries can be collapsed into a with_entries that replaces the map call.

jq '. | with_entries(select(.value | type | match("array"))' data.json
Enter fullscreen mode Exit fullscreen mode

with_entries(foo) is a shorthand for to_entries | map(foo) | from_entries, useful for doing some operation to all keys and values of an object.

This can be extended to select for multiple types with a little conditional logic like so:

jq '. | with_entries(select((.value | type) == "array" or (.value | type) == "object"))' data.json
Enter fullscreen mode Exit fullscreen mode

That's just a drop in the bucket for how jq can be used to explore JSON data files.

With this tool being so general-purpose and having so many utilities, workflows like this one are where things get most interesting. Share your jq workflows with me in the comments below 👇

If you enjoyed this post, consider joining my newsletter or following me on twitter. If this helped you or you have a question, feel free to drop me note wherever. I'd love to hear from you!

Top comments (0)