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 first.

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 ArticlesAnsible map Filter GuideAnsible Jinja2 Filters Complete ReferenceAnsible selectattr Filter GuideAnsible register: Save Task Output

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home