Use the combine filter.

- set_fact:
    mergedobject: "{{ object1.params | combine (object2.params) }}"
Answer from Thomas Hirsch on Stack Overflow
🌐
GitHub
gist.github.com › jpralves › 718c233a7e8f02f57fc46fe1a17196ff
Merge the content of a json file with another json file · GitHub
--- - name: get content of original file slurp: src: "original.json" register: original_config ignore_errors: yes - name: convert content to json and load merge json set_fact: original_json: "{{ original_config.content|default('e30=') | b64decode | from_json }}" merge_json: "{{ lookup('file', merge.json' ) | from_json }}" - name: merge content copy: content: "{{ original_json | combine(merge_json) | to_nice_json(indent=2) }}" dest: "new.json"
Discussions

Ansible-Merge two nested json files into single file of Json format - Stack Overflow
I am having two json and want to append one into another and save them in one file. I have done a set fact to read the values and put them in a variable using following: - name: Set json combine t... More on stackoverflow.com
🌐 stackoverflow.com
March 19, 2020
See how merge json with another in ansible
should define a default object user and groups variables to clean tasks More on github.com
🌐 github.com
2
November 11, 2015
jmespath - Combine attribute value using json_query in ansible - Stack Overflow
I want to combine two attribute into single string separated by delimiter using the json_query in ansible Sample data More on stackoverflow.com
🌐 stackoverflow.com
How do I create and store a list of dict/json objects?
- name: "Build list of dicts" set_fact: new_dict: " {{ new_list | combine(item.json ) }} " with_items: "{{ (artifactory_repo_info.results | list )}}" I get an error when I attempt this. Im sure there is a simple solution or this is one of those shortcomings of Ansible More on reddit.com
🌐 r/ansible
3
1
September 13, 2019
🌐
Ansible
docs.ansible.com › ansible › latest › playbook_guide › playbooks_filters.html
Using filters to manipulate data — Ansible Community Documentation
- shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release'] | int >= 6 · New in version 1.6. You can switch a data structure in a template from or to JSON or YAML format, with options for formatting, indenting, and loading data.
🌐
Google Groups
groups.google.com › g › ansible-project › c › Rra70UVLIac
merge json_query output
March 23, 2021 - https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#selecting-from-sets-or-lists-set-theory
🌐
LinuxTut
linuxtut.com › en › e948158fc54a9c6cf232
Merge JSON format data with Ansible
December 21, 2019 - --Judgment whether JSON Merge is installed by HAS_JSONMERGE --Returns a merge of two JSON data according to JSON Schema · from __future__ import absolute_import, division, print_function __metaclass__ = type from ansible.module_utils.six import PY3, string_types from ansible.errors import AnsibleError, AnsibleFilterError try: from jsonmerge import Merger HAS_JSONMERGE = True except ImportError: HAS_JSONMERGE = False class FilterModule(object): def jsonmerge(self, output1, output2, schema): if not HAS_JSONMERGE: raise AnsibleFilterError("JSONMerge not found.
🌐
Ansible
docs.ansible.com › projects › ansible › latest › collections › ansible › builtin › combine_filter.html
ansible.builtin.combine filter – combine two dictionaries — Ansible Community Documentation
This describes keyword parameters of the filter. These are the values key1=value1, key2=value2 and so on in the following example: input | ansible.builtin.combine(key1=value1, key2=value2, ...)
Find elsewhere
🌐
OpenDev
opendev.org › zuul › zuul-jobs › commit › 0b9fad9583794e3f35ff18250de8f6cf9ec31353
update-json-file: add role to combine values into a .json · 0b9fad9583 - zuul-jobs - OpenDev: Free Software Needs Free Tools
Ansible doens't really have a great built-in way to modify a json file (unlike ini files). The extant docker role does what seems to be the usual standard, which is slurp in the file, parse it and then write it back out. In a follow-on change (I338616c41a65b007d56648fdab6da2a6a6b909f4) we need…
🌐
Opensource.com
opensource.com › article › 21 › 4 › process-json-data-ansible
5 ways to process JSON data in Ansible | Opensource.com
April 28, 2021 - If the data is structured, you can leverage a wide array of options to make parsing it simpler and more consistent. Structured data conforms to a data model, which allows access to each data field separately. The data for these models is exchanged as key/value pairs and encoded using different formats. JSON, which is widely used in Ansible, is one of them.
Top answer
1 of 2
5

For example

    - debug:
        msg: "{{ locations|
                 json_query('[?state == `WA`].[name,state]')|
                 map('join', '-')|list }}"

gives

  msg:
  - Seattle-WA
  - Bellevue-WA
  - Olympia-WA

The same result gives the task below using Jinja2 filters only

    - debug:
        msg: "{{ _names|zip(_states)|map('join', '-')|list }}"
      vars:
        _locations: "{{ locations|selectattr('state', 'eq', 'WA')|list }}"
        _names: "{{ _locations|map(attribute='name')|list }}"
        _states: "{{ _locations|map(attribute='state')|list }}"

json_query issue (fixed in 2.10 and later)

There is JMESPath join. Unfortunately

    - debug:
        msg: "{{ locations|
                 json_query('[].join(`-`, [name,state])') }}"

fails

msg: |- JMESPathError in json_query filter plugin: In function join(), invalid type for value: Seattle, expected one of: ['array-string'], received: "AnsibleUnicode"

to_json|from_json workaround

Quoting from json_query: Add examples for starts_with and contains #72821

data structure returned from register variables needs to be parsed using to_json | from_json in order to get a correct result. Fixes: ansible-collections/community.general#320

    - debug:
        msg: "{{ locations|to_json|from_json|
                 json_query('[].join(`-`, [name,state])') }}"

gives

  msg:
  - Seattle-WA
  - New York-NY
  - Bellevue-WA
  - Olympia-WA
2 of 2
1

Just for the sake of a pure JMESPath way of doing it, as your trial and error solution still have an unneeded extra layer of complexity.

When you are doing

[?state == 'WA'].[join('-', [name, state])][]

You are creating an array [join('-', [name, state])] then flattening it [] for no reason.

You can just go to the solution with a shorter approach:

[?state == `WA`].join(`-`, [name, state])

Also mind that you can overcome the quotes in quotes (simple or double) complication for JMESPath queries using:

  1. YAML multilines string: How do I break a string in YAML over multiple lines?

  2. Backticks in your JMESPath query, as pointed in the documentation:

    In the example above, quoting literals using backticks avoids escaping quotes and maintains readability.

    Source: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#selecting-json-data-json-queries


So you end up with (see note below if you are on an Ansible version < 2.10):

- debug:
    msg: >-
      {{ test.locations 
           | json_query('[?state == `WA`].join(`-`, [name, state])') }}

Please note: as raised by @Vladimir Botka on the versions prior to 2.10, you will be affected by this issue: https://github.com/ansible/ansible/issues/27299#issuecomment-331068246, forcing you to add a | to_json | from_json filter on the list.


Given the playbook:

- hosts: all
  gather_facts: yes

  tasks:
    - debug:
        msg: >-
          {{ test.locations 
              | json_query('[?state == `WA`].join(`-`, [name, state])') 
          }}
      vars:
        test:
          locations:
            - name: Seattle
              state: WA
            - name: New York
              state: NY
            - name: Bellevue
              state: WA
            - name: Olympia
              state: WA

This yields:

[
    "Seattle-WA",
    "Bellevue-WA",
    "Olympia-WA"
]
🌐
Reddit
reddit.com › r/ansible › how do i create and store a list of dict/json objects?
r/ansible on Reddit: How do I create and store a list of dict/json objects?
September 13, 2019 - - name: "Build list of dicts" set_fact: new_dict: " {{ new_list | combine(item.json ) }} " with_items: "{{ (artifactory_repo_info.results | list )}}" I get an error when I attempt this. Im sure there is a simple solution or this is one of those shortcomings of Ansible ·
Top answer
1 of 1
3

You need to investigate the extra parameter that the combine filter is offering you:

The filter also accepts an optional recursive=True parameter to not only override keys in the first hash, but also recurse into nested hashes and merge their keys too

{{ {'a':{'foo':1, 'bar':2}, 'b':2} | combine({'a':{'bar':3, 'baz':4}}, recursive=True) }}

This would result in:

{'a':{'foo':1, 'bar':3, 'baz':4}, 'b':2}

See: https://docs.ansible.com/ansible/2.9/user_guide/playbooks_filters.html#combining-hashes-dictionaries


So in your case, you indeed have to combine you two dictionaries first, then, convert them in JSON:

- name: Combine existing S3 notifications with new notifications
      command: >
        aws s3api put-bucket-notification-configuration
          --bucket "{{ s3_notification.bucket }}"
          --notification-configuration '{{ s3_notification.configuration | combine(existing_s3_notifications, recursive=True) | to_json }}'
          --region "{{ aws_region }}"
      environment:
        AWS_ACCESS_KEY_ID: "{{ assumed_role.sts_creds.access_key }}"
        AWS_SECRET_ACCESS_KEY: "{{ assumed_role.sts_creds.secret_key }}"
        AWS_SECURITY_TOKEN: "{{ assumed_role.sts_creds.session_token }}"

Also mind that, if you are on version 2.10 already, you even have another extra parameter:

list_merge: Is a string, its possible values are replace (default), keep, append, prepend, append_rp or prepend_rp. It modifies the behaviour of combine when the hashes to merge contain arrays/lists.

See: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-hashes-dictionaries, containing nice examples for each values

🌐
GitHub
github.com › IBM › ansible-role-infosvr-import-export › issues › 23
Add module to merge multiple relationship JSON files · Issue #23 · IBM/ansible-role-infosvr-import-export
October 1, 2018 - Add a new module that will merge multiple relationship JSON files into a single file. This could then be used to merge a relationship file from a source environment with an export from the target e...
Author   cmgrote
🌐
Ansible
docs.ansible.com › projects › ansible › latest › collections › community › general › docsite › filter_guide_abstract_informations_merging_lists_of_dictionaries.html
Merging lists of dictionaries — Ansible Community Documentation
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the community.general.lists_mergeby filter. ... The output of the examples in this section use the YAML callback plugin. Quoting: “Ansible output that can be quite a bit easier to read than the default JSON formatting.” See the documentation for the community.general.yaml callback plugin.
🌐
Ansible
forum.ansible.com › archives › ansible project
how to join two json data structure to perform a join operation - Ansible Project - Ansible
September 8, 2017 - Hi I am very new with ansible and I am struggling to solve the following “problem” I have two json inputs a list of “locations” (you can think them as stores). For each "location"I have the name and the unique ID and a list of “parts” . For each item, I have an array which tells ...
🌐
Reddit
reddit.com › r/ansible › creating list of json problem
r/ansible on Reddit: Creating list of JSON problem
November 17, 2020 -

I'm trying to append a JSON object to an existing Json file but every time I run my code it just get replace.

- hosts: localhost

gather_facts: false

tasks:

- name: Create json file if doesn't exists

copy:

content: "{}"

dest: /root/BAND.json

force: no

- name: load var from file

include_vars:

file: /root/BAND.json

name: imported_var

- debug:

var: imported_var

- name: append more key/values

set_fact:

imported_var: "{{ imported_var | default([]) | combine({ 'Router1': 'R1', 'Router2': 'R2', 'ADDRESS1': '192.168.1.1', 'ADDRESS2': '192.168.22.2'}) }}"

- debug:

var: imported_var

- name: write var to file

copy:

content: "{{ imported_var | to_nice_json }}"

dest: /root/BAND.json

My code isn't creating a list and is replacing the json when I run the playbook. In reality I would like to make a LIST OF JSON objects and append new JSONs to the same file every time I run the code.

This is what I want
🌐
Ansible
docs.ansible.com › ansible › latest › collections › ansible › builtin › to_json_filter.html
ansible.builtin.to_json filter – Convert variable to JSON string — Ansible Community Documentation
This filter functions as a wrapper to the Python json.dumps function. Ansible internally auto-converts JSON strings into variable structures so this plugin is used to force it into a JSON string.
Top answer
1 of 1
3

Do not use nested curly braces "{{ ... {{ item }} ... }}". Correct syntax is

all_users: "{{ all_users+ [{ 'UserID': item,
                             'UserType': 'TBD',
                             'UserName': 'TBD' }] }}"

Next, it's more convenient to submit a list of userids. Then the split filter is not necessary. For example the playbook

shell> cat playbook.yml
- hosts: localhost
  tasks:
    - name: Initiate User List
      set_fact:
        all_users: []
    - name: Add new JSON Objects to List
      set_fact:
        all_users: "{{ all_users +
                       [{ 'UserID': item,
                          'UserType': 'TBD',
                          'UserName': 'TBD' }] }}"
      loop: "{{ userids }}"
    - name: Debug
      debug:
        var: all_users

gives

shell> ansible-playbook -e "userids=['123456','654321']" playbook.yml
...
    "all_users": [
        {
            "UserID": "123456",
            "UserName": "TBD",
            "UserType": "TBD"
        },
        {
            "UserID": "654321",
            "UserName": "TBD",
            "UserType": "TBD"
        }
    ]


Remove the single-quotes from the items in the list userids if the attribute UserID shall be stored as integer type instead of string. For example

shell> ansible-playbook -e "userids=[123456,654321]" playbook.yml

gives (there are no quotes around the values of UserID)

    "all_users": [
        {
            "UserID": 123456,
            "UserName": "TBD",
            "UserType": "TBD"
        },
        {
            "UserID": 654321,
            "UserName": "TBD",
            "UserType": "TBD"
        }
    ]

Then use a dictionary to create the list of users. For example,

shell> cat playbook.yml
- hosts: localhost
  vars:
    my_users:
      123456:
        name: Alice Admin
        type: admin
      654321:
        name: Bob Business
        type: sales
  tasks:
    - name: Initiate User List
      set_fact:
        all_users: []
    - name: Add new JSON Objects to List
      set_fact:
        all_users: "{{ all_users +
                       [{ 'UserID': item,
                          'UserType': my_users[item].type,
                          'UserName': my_users[item].name }] }}"
      loop: "{{ userids }}"
    - name: Debug
      debug:
        var: all_users

gives

shell> ansible-playbook -e "userids=[123456,654321]" playbook.yml
...
    "all_users": [
        {
            "UserID": 123456,
            "UserName": "Alice Admin",
            "UserType": "admin"
        },
        {
            "UserID": 654321,
            "UserName": "Bob Business",
            "UserType": "sales"
        }
    ]