Ansible Read JSON File: lookup file Plugin & from_json (Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
How to read JSON files into variables in Ansible using lookup file plugin and from_json filter. Load config files, parse data, and access nested values.

How to Read a JSON file into a variable on the host with Ansible?
The JSON (JavaScript Object Notation) is an open standard file format used a lot for data interchange. I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton, and welcome to today's episode of Ansible Pilot.
See also: Ansible lookup file Plugin: Read Local File Content into Variable (Guide)
Ansible reads a JSON file into a variable
•ansible.builtin.file - read file contents
• from_json filter - converts the variable to JSON.
Let's dive deep into the Ansible lookup plugin file.
Plugins are a way to expand the Ansible functionality. With lookup plugins specifically, you can load variables or templates with information from external sources.
The full name is ansible.builtin.file; it's part of ansible-core and is included in all Ansible installations.
The purpose of the file lookup plugin is to read file contents.
The "from_json" is an Ansible-specific filter to convert the input to JSON.
Let's combine the result of the file lookup plugin with the from_json filter for our use case.
Playbook
How to read the example.json JSON file, assign it to a variable and use it in your Ansible Playbook code.code
• example.json{
"name": "John",
"age": 30
}
• read_json.yml
---
- name: json read Playbook
hosts: localhost
vars:
jsondata: "{{ lookup('file', 'example.json') | from_json }}"
tasks:
- name: Print variable
ansible.builtin.debug:
var: jsondata
execution
$ ansible-playbook read_json.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the
implicit localhost does not match 'all'
PLAY [json read Playbook] *******************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [localhost]
TASK [Print variable] *******************************************************************
ok: [localhost] => {
"jsondata": {
"age": 30,
"name": "John"
}
}
PLAY RECAP ******************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
idempotency
$ ansible-playbook read_json.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the
implicit localhost does not match 'all'
PLAY [json read Playbook] *******************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [localhost]
TASK [Print variable] *******************************************************************
ok: [localhost] => {
"jsondata": {
"age": 30,
"name": "John"
}
}
PLAY RECAP ******************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Conclusion
Now you know how to read a JSON file into a variable on the host with Ansible.See also: Ansible from_json & to_json Filters: Parse & Generate JSON Data (Guide)
Read Local JSON File
- name: Load config
set_fact:
config: "{{ lookup('file', 'files/config.json') | from_json }}"
- debug:
msg: "DB host: {{ config.database.host }}, port: {{ config.database.port }}"
Read JSON Relative to Playbook
- set_fact:
settings: "{{ lookup('file', playbook_dir + '/settings.json') | from_json }}"
See also: Creating a Custom Ansible Lookup Plugin in Python for Reading a File
Read Remote JSON File
- name: Slurp remote JSON
ansible.builtin.slurp:
src: /etc/myapp/config.json
register: remote_file
- name: Parse it
set_fact:
remote_config: "{{ remote_file.content | b64decode | from_json }}"
- debug:
msg: "App mode: {{ remote_config.mode }}"
Read JSON from URL
- name: Fetch JSON API
ansible.builtin.uri:
url: https://api.example.com/config
return_content: true
register: api_response
- set_fact:
api_data: "{{ api_response.json }}" # Auto-parsed
# OR: "{{ api_response.content | from_json }}"
Use JSON Data in Tasks
- vars:
packages: "{{ lookup('file', 'packages.json') | from_json }}"
# packages.json: {"install": ["nginx", "curl", "git"]}
ansible.builtin.package:
name: "{{ packages.install }}"
state: present
become: true
Load Multiple JSON Files
- name: Load all config files
set_fact:
"config_{{ item | basename | splitext | first }}": "{{ lookup('file', item) | from_json }}"
loop: "{{ lookup('fileglob', 'configs/*.json', wantlist=True) }}"
Modify and Write Back
- set_fact:
config: "{{ lookup('file', 'config.json') | from_json }}"
- set_fact:
updated: "{{ config | combine({'version': '2.0', 'updated': true}) }}"
- ansible.builtin.copy:
content: "{{ updated | to_nice_json }}"
dest: /etc/myapp/config.json
become: true
Include Variables from JSON
# Alternative: include_vars (auto-detects format)
- name: Load JSON as variables
ansible.builtin.include_vars:
file: settings.json
name: settings
FAQ
file lookup vs include_vars — which should I use?
| Method | Scope | When to Use |
|--------|-------|-------------|
| lookup('file') | from_json | Set fact | Need to transform data |
| include_vars | Load as variables | Direct variable usage |
What if the JSON file doesn't exist?
- set_fact:
config: "{{ lookup('file', 'config.json', errors='ignore') | default('{}') | from_json }}"
Can I read JSON from a Jinja2 template?
Yes:
{% set config = lookup('file', 'config.json') | from_json %}
{{ config.server.host }}
Read Local JSON File
- set_fact:
config: "{{ lookup('file', 'config.json') | from_json }}"
- debug:
msg: "DB: {{ config.database.host }}:{{ config.database.port }}"
Read Remote JSON File
- slurp:
src: /etc/myapp/config.json
register: remote_file
- set_fact:
config: "{{ remote_file.content | b64decode | from_json }}"
- debug:
msg: "App version: {{ config.version }}"
Include Variables from JSON
# vars/config.json
# {"db_host": "localhost", "db_port": 5432, "debug": true}
- hosts: all
vars:
config: "{{ lookup('file', 'vars/config.json') | from_json }}"
tasks:
- debug: msg="{{ config.db_host }}"
Read and Filter
- set_fact:
all_servers: "{{ lookup('file', 'servers.json') | from_json }}"
- set_fact:
prod_servers: "{{ all_servers | selectattr('env', 'eq', 'production') | list }}"
server_names: "{{ all_servers | map(attribute='name') | list }}"
Read Multiple JSON Files
- set_fact:
db_config: "{{ lookup('file', 'db.json') | from_json }}"
app_config: "{{ lookup('file', 'app.json') | from_json }}"
merged: "{{ (lookup('file', 'defaults.json') | from_json) | combine(lookup('file', 'overrides.json') | from_json) }}"
Conditional Based on JSON
- set_fact:
features: "{{ lookup('file', 'features.json') | from_json }}"
- name: Enable caching
template:
src: cache.conf.j2
dest: /etc/myapp/cache.conf
when: features.caching.enabled
- name: Configure monitoring
template:
src: monitoring.conf.j2
dest: /etc/myapp/monitoring.conf
when: features.monitoring.enabled
Dynamic Inventory from JSON
# hosts.json
# {"webservers": ["web1", "web2"], "dbservers": ["db1"]}
- set_fact:
host_data: "{{ lookup('file', 'hosts.json') | from_json }}"
- debug:
msg: "Web servers: {{ host_data.webservers | join(', ') }}"
Error Handling
# File might not exist
- set_fact:
config: "{{ lookup('file', 'optional.json', errors='ignore') | default('{}') | from_json }}"
# With stat check
- stat: { path: files/config.json }
register: config_file
delegate_to: localhost
- set_fact:
config: "{{ lookup('file', 'config.json') | from_json }}"
when: config_file.stat.exists
lookup('file') vs include_vars
| Method | Source | Format | Scope |
|--------|--------|--------|-------|
| lookup('file') \| from_json | Controller | JSON | set_fact/vars |
| include_vars | Controller | YAML/JSON | Play vars |
| slurp \| from_json | Remote | JSON | set_fact |
| uri \| .json | HTTP | JSON | register |
# include_vars works directly with JSON
- include_vars:
file: config.json
name: config
FAQ
lookup('file') vs slurp?
lookup('file') reads from the controller machine. slurp reads from the remote host. Use lookup for local config files, slurp for remote files.
Can I write back to a JSON file?
- copy:
content: "{{ modified_config | to_nice_json }}"
dest: files/config.json
delegate_to: localhost
What if the JSON is invalid?
from_json will fail with a parse error. Validate your JSON files before using them.
Related Articles
• Jinja2 filters in Ansible templates • Ansible inventory groups and variables • Ansible JSON Conversion Guide • attribute management via ansible.builtin.fileCategory: installation
Watch the video: Ansible Read JSON File: lookup file Plugin & from_json (Guide) — Video Tutorial