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!

API Trace View

How I Cut 22.3 Seconds Off an API Call with Sentry 🕒

Struggling with slow API calls? Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more