Ansible from_json & to_json Filters: Parse & Generate JSON Data (Guide)
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to parse and generate JSON in Ansible with from_json, to_json, to_nice_json filters. Convert strings to dicts, format output, API responses.
What Are from_json and to_json Filters?
The from_json and to_json filters convert data between JSON strings and Ansible data structures:
• from_json: Parses a JSON string into a dictionary or list
• to_json: Converts a variable (dict, list) into a JSON string
• to_nice_json: Converts to human-readable formatted JSON
See also: Ansible Read JSON File: lookup file Plugin & from_json (Guide)
from_json: Parse JSON Strings
Use from_json when you receive JSON as a string (from API calls, command output, file reads):
---
- name: Parse JSON data
hosts: localhost
vars:
json_string: '{"name": "web-server", "port": 8080, "enabled": true}'
tasks:
- name: Parse JSON string into variable
ansible.builtin.set_fact:
server_config: "{{ json_string | from_json }}"
- name: Access parsed data
ansible.builtin.debug:
msg: "Server {{ server_config.name }} runs on port {{ server_config.port }}"
Parse JSON from Command Output
- name: Get Docker container info
ansible.builtin.command: docker inspect my-container
register: docker_output
- name: Parse Docker inspect JSON
ansible.builtin.set_fact:
container_info: "{{ docker_output.stdout | from_json }}"
- name: Show container IP
ansible.builtin.debug:
msg: "Container IP: {{ container_info[0].NetworkSettings.IPAddress }}"
Parse JSON from File
- name: Read JSON config file
ansible.builtin.slurp:
src: /etc/app/config.json
register: config_file
- name: Parse file content
ansible.builtin.set_fact:
app_config: "{{ config_file.content | b64decode | from_json }}"
- name: Use config values
ansible.builtin.debug:
msg: "Database: {{ app_config.database.host }}:{{ app_config.database.port }}"
to_json: Convert to JSON Strings
Use to_json to convert Ansible variables to JSON format:
- name: Convert variable to JSON
ansible.builtin.debug:
msg: "{{ my_dict | to_json }}"
# Output: {"key1": "value1", "key2": "value2"}
Write JSON to File
- name: Write config as JSON file
ansible.builtin.copy:
content: "{{ app_config | to_nice_json }}"
dest: /etc/app/config.json
mode: '0644'
Send JSON in API Requests
- name: Send data to API
ansible.builtin.uri:
url: https://api.example.com/servers
method: POST
body: "{{ server_data | to_json }}"
body_format: json
headers:
Content-Type: application/json
See also: Ansible Jinja2 Filters: Transform Data in Playbooks (Complete Reference)
to_nice_json: Human-Readable Output
to_nice_json produces formatted, indented JSON:
- name: Pretty-print JSON
vars:
config:
server:
name: web-01
port: 443
database:
host: db-01
port: 5432
ansible.builtin.debug:
msg: "{{ config | to_nice_json }}"
Output:
{
"server": {
"name": "web-01",
"port": 443
},
"database": {
"host": "db-01",
"port": 5432
}
}
Control Indentation
# 2-space indent
msg: "{{ config | to_nice_json(indent=2) }}"
# Sort keys alphabetically
msg: "{{ config | to_nice_json(sort_keys=True) }}"
# Both
msg: "{{ config | to_nice_json(indent=2, sort_keys=True) }}"
to_nice_yaml: Convert to YAML Format
Convert variables to readable YAML:
- name: Output as YAML
ansible.builtin.debug:
msg: "{{ config | to_nice_yaml }}"
- name: Write YAML file
ansible.builtin.copy:
content: "{{ config | to_nice_yaml }}"
dest: /etc/app/config.yaml
See also: Ansible map vs selectattr vs json_query: Filter Data the Right Way
Common Patterns
Chain Filters
# Read file → decode → parse JSON → extract value
- name: Get database host from JSON config
ansible.builtin.set_fact:
db_host: "{{ lookup('file', 'config.json') | from_json | json_query('database.host') }}"
Handle JSON in Loops
- name: Process JSON array
vars:
servers_json: '[{"name":"web-1","port":80},{"name":"web-2","port":8080}]'
ansible.builtin.debug:
msg: "{{ item.name }} on port {{ item.port }}"
loop: "{{ servers_json | from_json }}"
Merge and Convert
- name: Merge configs and write JSON
vars:
defaults:
log_level: info
timeout: 30
overrides:
timeout: 60
debug: true
ansible.builtin.copy:
content: "{{ defaults | combine(overrides) | to_nice_json }}"
dest: /etc/app/config.json
Error Handling
Invalid JSON
- name: Safely parse JSON
block:
- name: Parse potentially invalid JSON
ansible.builtin.set_fact:
data: "{{ maybe_json | from_json }}"
rescue:
- name: Handle parse error
ansible.builtin.debug:
msg: "Failed to parse JSON: {{ maybe_json }}"
Default Values
# Use default if key doesn't exist
- name: Safe access with defaults
ansible.builtin.debug:
msg: "Port: {{ (json_string | from_json).port | default(8080) }}"
FAQ
What is the difference between from_json and from_yaml?
from_json parses JSON strings only. from_yaml parses YAML strings (which is a superset of JSON). In practice, from_yaml can also parse JSON, but from_json is stricter and preferred when you know the input is JSON.
When do I need from_json vs just accessing the variable?
You need from_json when the data is a string containing JSON, not a parsed data structure. This happens with command output (register), file reads (slurp), and API responses returned as strings. If the variable is already a dict/list, you don't need it.
How do I handle nested JSON with special characters?
Use bracket notation for keys with dots or spaces: {{ (json_str | from_json)['my.key']['with spaces'] }}. For complex nested queries, use the json_query filter with JMESPath syntax.
Related Articles
• Ansible Jinja2 Filters Guide • Ansible map Filter • Ansible dict2items & items2dict • Ansible combine FilterCategory: troubleshooting