# Ansible's handling of string representation of complex objects

**URL:** <https://forum.ansible.com/t/ansibles-handling-of-string-representation-of-complex-objects/30863>\
**Category:** Ansible Project\
**Created:** [July 24, 2019, 9:58pm UTC](https://forum.ansible.com/t/ansibles-handling-of-string-representation-of-complex-objects/30863 "2019-07-24T21:58:51Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Guy\_Knights1](https://avatars.discourse-cdn.com/v4/letter/g/82dd89/32.png) [@Guy\_Knights1](https://forum.ansible.com/u/Guy_Knights1)\
**Post date:** [July 24, 2019, 9:58pm UTC](https://forum.ansible.com/t/ansibles-handling-of-string-representation-of-complex-objects/30863/1 "2019-07-24T21:58:51Z")

</div>

I’ve run into a weird behaviour regarding how Ansible handles converting strings to complex objects.

I have the following string representation of a list of dicts that I’m returning from a Cloudformation stack output:

[{“id”: “subnet-f3i4ven6lxvxr3eu”,“az”: “us-east-1a”},{“id”: “subnet-0wovp0yu5sr8pnwv”,“az”: “us-east-1b”}]

I’ve been using this in a playbook, passing it to the “loop” parameter in the following task:

- name: provision instances  
ec2:  
key\_name: keypair1  
instance\_type: t2.micro  
image: “{{ ami\_id }}”  
wait: no  
exact\_count: 1  
count\_tag:  
Name: “instance{{ loop\_count + 1 }}”  
Type: type1  
AZ: “{{ [item.az](http://item.az) }}”  
group\_id: “{{ cf\_results.stack\_outputs.SecurityGroupDetails|from\_json|map(attribute=‘id’)|list }}”  
termination\_protection: yes  
vpc\_subnet\_id: “{{ [item.id](http://item.id) }}”  
volumes:
- device\_name: /dev/sda1  
volume\_type: gp2  
volume\_size: 50  
delete\_on\_termination: true  
instance\_tags:  
Name: “instance{{ loop\_count + 1 }}”  
Type: type1  
Environment: prod  
VPC: vpc1  
Subnet: “{{ [item.name](http://item.name) }}”  
AZ: “{{ [item.az](http://item.az) }}”  
monitoring: yes  
region: us-east-1  
loop: “{{ cf\_results.stack\_outputs.SubnetDetails }}”  
loop\_control:  
index\_var: loop\_count  
register: instances

The above task works fine. However, I’ve been trying to use it to create another, single EC2 instance and I’m using filters to just select the first subnet from the list, as follows:

- name: provision vpn instance  
ec2:  
key\_name: keypair1  
instance\_type: t2.micro  
image: “{{ ami\_id }}”  
wait: no  
exact\_count: 1  
count\_tag:  
Name: extra\_instance  
Type: type2  
AZ: “{{ cf\_results.stack\_outputs.SubnetDetails[0].az }}”  
group\_id: “{{ cf\_results.stack\_outputs.SecurityGroupDetails|from\_json|map(attribute=‘id’)|list }}”  
termination\_protection: yes  
vpc\_subnet\_id: “{{ cf\_results.stack\_outputs.SubnetDetails[0].id }}”  
assign\_public\_ip: yes  
instance\_tags:  
Name: extra\_instance  
Type: type2  
Environment: prod  
VPC: vpc1  
Subnet: “{{ cf\_results.stack\_outputs.SubnetDetails[0].id }}”  
AZ: “{{ cf\_results.stack\_outputs.SubnetDetails[0].az }}”  
monitoring: yes  
region: “{{ static\_config.region }}”

register: extra\_instance

When the above task is executed it fails with the following error: “The task includes an option with an undefined variable. The error was: ‘str object’ has no attribute ‘az’”.

I added a ‘debug’ task to just output the first item from the list, it worked but as you can see it just outputs the first character in the string:

TASK [debug] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> {  
“cf\_results.stack\_outputs.SubnetDetails[0]”: “[”

}

Is there a reason why the loop parameter successfully converts the string to a list but the filter doesn’t?

Thanks,  
Guy

---

<div class="post-metadata">

**Author:** ![sivel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/sivel/32/1198_2.png) [@sivel](https://forum.ansible.com/u/sivel)\
**Post date:** [July 24, 2019, 10:07pm UTC](https://forum.ansible.com/t/ansibles-handling-of-string-representation-of-complex-objects/30863/2 "2019-07-24T22:07:19Z")

</div>

Due to some historical integrations between ansible and jinja2, we try to convert things that look like python data structures, to actual python data structures. This is because historically, jinja2 could only return string representations of python data structures, not actual python data structures.

Because you have to template out the value to pass to the loop, it get’s magically converted to a python DS before it hits the loop.

This happens in: [https://github.com/ansible/ansible/blob/e32d60bbcd44ccc7761268c6d6f00db036db962b/lib/ansible/template/ **init**.py#L577-L590](https://github.com/ansible/ansible/blob/e32d60bbcd44ccc7761268c6d6f00db036db962b/lib/ansible/template/ __init__.py#L577-L590)

It only happens if the result of the template action produces something that starts with `{` or `[`

So in your second case, you are trying to access an element of a string.

Looking in your first task I see you are using the following:

group\_id: “{{ cf\_results.stack\_outputs.SecurityGroupDetails|from\_json|map(attribute=‘id’)|list }}”

You would need to do something like that, where you use `from_json` in your other uses.
