'Ansible: Error reading JSON: Invalid data passed to 'loop', it requires a list, got this instead
Here is my JSON
[
{
"?xml": {
"attributes": {
"encoding": "UTF_8",
"version": "1.0"
}
}
},
{
"jdbc_data_source": [
{
"attributes": {
"xmlns": "http://xmlns.oracle.com/weblogic/jdbc_data_source"
}
},
{
"name": "canwebds"
},
{
"jdbc_driver_params": [
{
"url": "jdbc:oracle:thin:@//myhost.mrshmc.com:1521/OLTT206"
},
{
"driver_name": "oracle.jdbc.OracleDriver"
},
{
"properties": {
"property": [
{
"name": "user"
},
{
"value": "WEB_USER"
}
]
}
},
{
"password_encrypted": "{AES}BcqmURyYoCkLvC5MmREXsfpRMO93KPIubqUAbb95+nE="
}
]
},
{
"jdbc_connection_pool_params": [
{
"initial_capacity": "1"
},
{
"statement_cache_type": "LRU"
}
]
},
{
"jdbc_data_source_params": {
"jndi_name": "canwebds"
}
}
]
},
{
"?xml": {
"attributes": {
"encoding": "UTF_8",
"version": "1.0"
}
}
},
{
"jdbc_data_source": [
{
"attributes": {
"xmlns": "http://xmlns.oracle.com/weblogic/jdbc_data_source"
}
},
{
"name": "dsARSVelocity"
},
{
"jdbc_driver_params": [
{
"url": "jdbc:oracle:thin:@myhost:1521:DB01"
},
{
"driver_name": "oracle.jdbc.OracleDriver"
},
{
"properties": {
"property": [
{
"name": "user"
},
{
"value": "AP05"
}
]
}
},
{
"password_encrypted": "{AES}wP5Se+OQdR21hKiC2fDw1WPEaTMU5Sc17Ax0+rmjmPI="
}
]
},
{
"jdbc_connection_pool_params": [
{
"initial_capacity": "1"
},
{
"statement_cache_type": "LRU"
}
]
},
{
"jdbc_data_source_params": [
{
"jndi_name": "dsARSVel"
},
{
"global_transactions_protocol": "OnePhaseCommit"
}
]
}
]
}
]
I need to print the below for any jdbc_data_source found
expected output:
jdbc_data_source name is has username and jndi name <jndi_name>
which will translate as:
jdbc_data_source name is cwds has username CAN_USER and jndi name cwdsjndi
Below is something i tried but it does not work:
- name: create YML for server name with DB
debug:
msg: "{{ dsname.0.name }} has jndi {{ dsurl[0]['jdbc_driver_params'][2]['properties][0]['property'][1]['value'] }}"
loop: "{{ jsondata[1] }}"
vars:
dsname: "{{ item.jdbc_data_source| selectattr('name', 'defined') | list }}"
dsurl: "{{ item.jdbc_data_source| selectattr('jdbc_driver_params', 'defined') | list }}"
However, it does not get me the desired output. Below is the error i get:
fatal: [localhost]: FAILED! => {"msg": "Invalid data passed to 'loop', it requires a list, got this instead: {'jdbc_data_source': [{'attributes': {'xmlns': 'http://xmlns.oracle.com/weblogic/jdbc_data_source', 'xml
If I loop loop: "{{ jsondata }}", then it works but the desired values still do not get printed.
Kindly suggest.
Solution 1:[1]
this playbook does the job:
- hosts: localhost
gather_facts: no
vars:
json: "{{ lookup('file', 'file.json') | from_json }}"
tasks:
- name: display datas
debug:
msg: "jdbc_data_source name is {{ name }} has username: {{ user }} and jndi name: {{ jndiname }}"
loop: "{{ json }}"
when: item.jdbc_data_source is defined
vars:
datasource1: "{{ item.jdbc_data_source | selectattr('jdbc_driver_params', 'defined') }}"
properties: "{{ (datasource1.0.jdbc_driver_params | selectattr('properties', 'defined')).0.properties }}"
name: "{{ (item.jdbc_data_source | selectattr('jdbc_data_source_params', 'defined')).0.jdbc_data_source_params.jndi_name }}"
user: "{{ (properties.property | selectattr('value', 'defined')).0.value }}"
jndiname: "{{ (item.jdbc_data_source | selectattr('name', 'defined') ).0.name}}"
result:
skipping: [localhost] => (item={'?xml': {'attributes': {'encoding': 'UTF_8', 'version': '1.0'}}})
ok: [localhost] => "msg": "jdbc_data_source name is cwds has username: CAN_USER and jndi name: cwdsjndi"
}
skipping: [localhost] => (item={'?xml': {'attributes': {'encoding': 'UTF_8', 'version': '1.0'}}})
ok: [localhost] => "msg": "jdbc_data_source name is dsvelcw has username: WEB_USER and jndi name: dsvelcw"
if you have a mixed of list and dictionary, change:
vars:
datasource1: "{{ item.jdbc_data_source | selectattr('jdbc_driver_params', 'defined') }}"
properties: "{{ (datasource1.0.jdbc_driver_params | selectattr('properties', 'defined')).0.properties }}"
params: "{{ (item.jdbc_data_source | selectattr('jdbc_data_source_params', 'defined')).0.jdbc_data_source_params }}"
name: "{{ params.jndi_name if params is mapping else (params | selectattr('jndi_name', 'defined')).0.jndi_name }}"
user: "{{ (properties.property | selectattr('value', 'defined')).0.value }}"
jndiname: "{{ (item.jdbc_data_source | selectattr('name', 'defined') ).0.name}}"
i test if its a dict else its a list..
result with new json:
skipping: [localhost] => (item={'?xml': {'attributes': {'encoding': 'UTF_8', 'version': '1.0'}}})
"msg": "jdbc_data_source name is canwebds has username: WEB_USER and jndi name: canwebds"
}
skipping: [localhost] => (item={'?xml': {'attributes': {'encoding': 'UTF_8', 'version': '1.0'}}})
"msg": "jdbc_data_source name is dsARSVel has username: AP05 and jndi name: dsARSVelocity"
}
some explanations:
(item.jdbc_data_source | selectattr('jdbc_data_source_params', 'defined')) selectattr create a list with all keys jdbc_data_source_params present in the list jdbc_data_source, here there are only one key jdbc_data_source_params, so the 0.jdbc_data_source_params selects the first key.
then we check if params is a dict else its a list
if you want to understand, i suggest you to decompose in lot of actions and display with debug the result.
FYI selectattr equivalent with json_query
selectattr('something', 'defined') = json_query("[?something]")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
