Ansible read JSON file - JSON file Parsing

In this article, we are going to see how to read the JSON file in ansible-playbook

JSON is the most famous data representation it is widely used to store and transmit data. When you are working in Ansible automation, you might get a requirement to work with JSON files and read JSON files into Ansible playbook and process the data and store the data as a variables.

In general, JSON data can be processed easily with json_query module of ansible and you can read more about it in our previous article

Our primary objective of this article is to talk about how to process the JSON FILE and read the JSON file into ansible playbook and process it.

in the previous article, we have talked about how to directly use the JSON output of a website or URL and use it for further processing. but now we are going to use the file as our source of data in this article.

we are going to take some sample JSON file which contains elements and sub elements in both array and single line formats, to understand this better.

 

Sample JSON file for our testing

This is the JSON file we are going to be using this article. the file name is config.json it was ideally designed for weblogic ansible installation setup but this can serve as a viable example in here.

{
    "domain":{
           "name": "mwidomain",
           "prod_mode": "prod",
           "user": "weblogic",
           "password": "weblogic1",

           "admin": {
            "servername": "AdminServer",
            "listenport": "8001"
            },

            "machines": [
                {
                    "refname": "Machine1",
                    "name": "MWINODE01"
                },
                {
                    "refname": "Machine2",
                    "name": "MWINODE02"
                }
            ],

            "clusters": [
                {
                    "refname": "Cluster1",
                    "name": "App1Cluster",
                    "machine": "Box1"
                },
                {
                    "refname": "Cluster2",
                    "name": "App2Cluster",
                    "machine": "Box2"
                }
            ],
            "servers": [
                {
                    "name": "ms1",
                    "port": 9001,
                    "machine": "Box1",
                    "clusterrefname": "Cluster1"
                },
                {
                    "name": "ms2",
                    "port": 9002,
                    "machine": "Box2",
                    "clusterrefname": "Cluster2"
                },
                {
                    "name": "ms3",
                    "port": 9003,
                    "machine": "Box1",
                    "clusterrefname": "Cluster1"
                },
                {
                    "name": "ms4",
                    "port": 9004,
                    "machine": "Box2",
                    "clusterrefname": "Cluster2"
                }
            ]

    }
}

 

 

How to read JSON file into ansible playbook

To read JSON file into the ansible playbook, ansible has given us a filter named from_json

but, of course, we need to use it along with few more commands and module like shell to read the json file.

here is the quick ansible playbook example that reads JSON file

---
  - name: ReadJsonfile
    hosts: localhost
    tasks:
      - name: Display the JSON file content
        shell: cat config.json
        register: result

      - name: save the Json data to a Variable as a Fact
        set_fact:
          jsondata: "{{ result.stdout | from_json }}"

Let us see how this playbook works.

 

  • The First task or play is to display the json file using the normal Shell command cat at this same tasks we are saving this output into a ansible register variable named result

 

  • The Second task or play is to read the register variable of the previous task named result and convert that into a proper json data, this is done using from_json filter  and then we store it into a new ansible fact variable named jsondata

 

  • Now we have our JSON file content stored in jsondata variable after being formatted as proper JSON, which can be easily parsed now using ansible json query module.

 

As simple as that we have now learnt how to read JSON data into ansible playbook using from_json and shell module.

 

 

How to use the JSON data in your playbook as a variable

So now we have processed the JSON file and imported it into our playbook but here comes the next part of the equation. So how are we going to use this JSON data in our playbook or store it as a variable?

Refer the following ansible playbook, A continuation of our previous read json playbook, in this ansible playbook we are taking out the necessary elements/keys and using in our playbook by setting it as ansible fact.

once the values are stored as ansible fact. it can be referred from anywhere in the playbook or ansible role using jinja 2 syntax {{ }}

---
  - name: ReadJsonfile
    hosts: localhost
    tasks:
      - name: Display the JSON file content
        shell: cat config.json
        register: result

      - name: save the Json data to a Variable as a Fact
        set_fact:
          jsondata: "{{ result.stdout | from_json }}"

      - name: setDomainName
        set_fact:
          domain_name: "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: 'domain.name'

      - name: setDomainUsername
        set_fact:
          domain_username: "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: 'domain.user'

      - name: setDomainPassword
        set_fact:
          domain_password: "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: 'domain.password'

      - name: setadmin_Listenport
        set_fact:
          admin_ListenPort: "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: 'domain.admin.listenport'

      - name: Debug the values
        debug: msg=" Admin Listen Port => {{ admin_ListenPort }}, DomainName => {{ domain_name }}, DomainUserName => {{ domain_username }} , Domain Password => {{ domain_password }}"

 

Explanation of this playbook.

  • Other than the previously explained two tasks/plays of shell and from_json  we have more tasks added with set_fact in this playbook

 

  • set_fact is used to create a new ansible variable at a run time of the playbook. we can also call it as run time variables or dynamic variables.

 

  • To filter out the required key or element from an otherwise big JSON data set. we are here using ansible  jmes_query which has been covered in detail here

 

  • vars is used to set a limited variable for every task/play.  it was primarily used to create a variable named jmesquery which contains the actual jmesquery

 

  • The Last play or task in this playbook is to display the created facts/variables using set_fact.

 

Execution result of this playbook

Here is the output of the playbook.

 

 

Complex JSON JMES Queries and Ansible Playbook

Sometimes we would want to create a list from the JSON data like a Dictionary or array. Or let's say we want to find all the server names and their ports from the JSON we have taken for example.

here is the playbook that creates a dictionary of data by processing the JSON file.

It simply creates a list or dictionary of servers and their port numbers.

---
  - name: ReadJsonfile
    hosts: localhost
    tasks:
      - name: Display the JSON file content
        shell: cat config.json
        register: result
      
      - name: save the Json data to a Variable as a Fact
        set_fact: 
          jsondata: "{{ result.stdout | from_json }}"

      - name: Server Names
        set_fact:  
          servernames:  "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: '*.servers[*].name'
      
      - name: Server Names and Ports
        set_fact:  
          serverinfo:  "{{ jsondata | json_query(jmesquery) }}"
        vars:
          jmesquery: '*.servers[*].[name, port]'
      
      - name: Print all server names
        debug: 
          msg: "{{ item}}"
        with_items: 
          - "{{ servernames }}"

      - name: Print all server names
        debug: 
          msg: "{{ item }}"
        with_items: 
        - "{{ serverinfo }}"

Explanation

  • With the help of jmespath queries, we are filtering out the Server names and Server Names with Port number like the same way we did in the previous playbook examples.
  • Now we are printing all the server names using the loop iteration with_items

 

Result of the playbook


Ansible JSON

 

Conclusion

I hope this article was helpful to understand how to read and process JSON file with Ansible. Feel free to ask in comments if you have any questions.

Cheers
Sarav

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading