Home > other >  unable to ideally parse a json file in ansible
unable to ideally parse a json file in ansible

Time:03-14

Below is my sample JSON file.

[
   {
      "?xml": {
         "attributes": {
            "encoding": "UTF-8",
            "version": "1.0"
         }
      }
   },
   {
      "domain": [

         {
            "server": [
               {
                  "name": "myserv1"
               },
               {
                  "ssl": {
                     "name": "myserv1"
                  }
               },
               {
                  "log": [
                     {
                        "name": "myserv1"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
                     }
                  ]
               }
            ]
         },
         {
            "server": [
               {
                  "name": "myserv2"
               },
               {
                  "ssl": {
                     "name": "myserv2"
                  }
               },
               {
                  "log": [
                     {
                        "name": "myserv2"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
                     }
                  ]
               }
            ]
         }
      ]
   }
]

My requirement is to read the json file and store the value in a file like below:

myserv1_log: "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
myserv2_log: "/web/bea_logs/domains/mydom/myserv2/myserv2.log"

i.e

<server>_log: <file-name>

Here is my Ansible play that uses JMESPath query to read the json data.

- name: Server Names and log details
  set_fact:
    serverlog:  "{{ jsondata | json_query(jmesquery) }}"
  vars:
    jmesquery: '[].domain[].server[*].log[*].[name, "file-name"]'

- name: Print all server names with log details
  debug:
    msg: "{{ item }}"
  with_items:
    - "{{ serverlog }}"

As you can see I get several null values in the output

output:

TASK [Print all server names with log details] *********************************
Wednesday 02 March 2022  03:17:45 -0600 (0:00:00.100)       0:00:04.730 *******
ok: [localhost] => (item=[]) => {
    "msg": []
}
ok: [localhost] => (item=[[['myserv1', None], [None, '/web/bea_logs/domains/mydom/myserv1/myserv1.log']]]) => {
    "msg": [
        [
            [
                "myserv1",
                null
            ],
            [
                null,
                "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
            ]
        ]
    ]
}

I tied to get rid of the null using the below but that too does not get me the desired output:

 - name: test
   set_fact:
     list2: "{{list2    [item]}}"
   when: item != "null"
   with_items:
     - "{{serverlog}}"

 - name: Neww Print all server names with log details
   debug:
     msg: "{{ item }}"
   with_items:
     - "{{ list3 }}"

I also tried the solution proposed on StackOverflow but I get error:

"{{ jsondata | selectattr('domain', 'defined') | map(attribute='domain') | flatten | map(attribute='server') | flatten | selectattr('log', 'defined') | map(attribute='log') | map('combine') }}"

Output error:

The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'server'\n\nThe error appears to be in....

Any earlier similar post did not get any working solution is why I decided to post here:

remove null elements from list ansible

Kindly suggest.

CodePudding user response:

the structure of your json is always the same no need to use jmepath:

- hosts: localhost
  gather_facts: no
  vars:
    json: "{{ lookup('file', './file.json') | from_json }}"
  tasks:
    - name: display
      debug:
        msg: "name: {{ servername }} --> filename: {{ filename }}"
      loop: "{{ json[1].domain }}"
      vars:
        servername: "{{ item.server.0.name }}_log"
        filename: "{{ item['server'][2]['log'][1]['file-name'] }}"

result:

ok: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': {'name': 'myserv1'}}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]}) => {
    "msg": "name: myserv1_log --> filename: /web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}]}) => {
    "msg": "name: myserv2_log --> filename: /web/bea_logs/domains/mydom/myserv2/myserv2.log"
}

some explanations: json is an array with 2 records one with key ?xml the other with key domain

domain is an array with key server

server is an array witk the differents keys name, ssl and log

log is an array with differents keys name and file-name


json[1].domain just keeps the part containing domain, json[0] contains the header of json

item.server.0.name (= item['server'][0]['name']) is the first item of record server which contains the key name

item['server'][2]['log'][1]['file-name'] is the third item for a record server which contains the key log and the second item of log contains the key file-name

  • Related