Ansible map vs selectattr vs json_query: Filter Data the Right Way
By Luca Berton · Published 2024-01-01 · Category: installation
Complete comparison of Ansible map, selectattr, and json_query filters with practical examples. Learn when to use each for transforming lists, filtering dictionaries by attribute, and querying nested JSON structures in playbooks.
Ansible offers three main approaches for filtering and transforming data: map, selectattr, and json_query. They solve different problems, and picking the wrong one creates unreadable playbooks. This guide shows when and how to use each.
Quick Comparison
| Filter | Purpose | Input | Syntax | |--------|---------|-------|--------| | map | Transform each item in a list | Lists | Jinja2 native | | selectattr | Filter list of dicts by attribute | List of dicts | Jinja2 native | | json_query | Query nested JSON structures | Any JSON | JMESPath (requires jmespath pip package) |
map: Transform Every Item
map applies a filter or extracts an attribute from every item in a list.
Extract Attribute from List of Dicts
Apply Filter to Each Item
map with format
When to Use map • Extracting one field from a list of objects • Applying a transformation to every item • Building new lists from existing data • Chaining with other filters (| map(...) | select(...) | list)
selectattr: Filter by Attribute
selectattr keeps only items from a list of dictionaries where an attribute matches a condition.
Basic Filtering
Available Tests
Chaining selectattr with map
When to Use selectattr • Filtering a list of dicts by one or more attributes • "Give me all items where X equals Y" • Replacing loop + when with a filter expression • Building filtered lists for other tasks
selectattr vs loop + when
json_query: Query Nested JSON
json_query uses JMESPath syntax for complex nested JSON queries. It's the most powerful option but requires the jmespath Python package.
Installation
Basic Query
Complex Queries
When to Use json_query • Deeply nested JSON (3+ levels) • Complex multi-condition filtering • API responses with irregular structure • When you need JMESPath functions (sort_by, max_by, contains, etc.) • Selecting/renaming specific fields from objects
Side-by-Side Comparison
Task: Get names of running servers
Task: Get servers in us-east with > 4 CPUs
Task: Extract nested field
Decision Guide
FAQ
Do I need to install jmespath for json_query?
Yes. json_query requires the jmespath Python package on the Ansible controller. Install with pip install jmespath. The map and selectattr filters are built into Jinja2 and require no additional packages.
Which filter is fastest?
map and selectattr are Jinja2-native and slightly faster for simple operations. json_query has overhead from JMESPath compilation but handles complex queries more efficiently than chaining multiple Jinja2 filters.
Can I chain map and selectattr?
Yes — this is the recommended pattern. Filter first with selectattr, then transform with map: {{ items | selectattr('active') | map(attribute='name') | list }}.
Why does my json_query return None?
Common causes: backtick quoting (JMESPath uses backticks for literals, not single quotes), wrong path depth, or the jmespath package is not installed. Test queries at
Conclusion
Use map to transform lists, selectattr to filter by attributes, and json_query for complex nested JSON. For most Ansible work, selectattr + map covers 90% of needs without external dependencies. Reserve json_query for deeply nested API responses.
Related Articles • Ansible map Filter Guide • Ansible Jinja2 Filters Complete Reference • Ansible selectattr Filter Guide • Ansible register: Save Task Output
Category: installation