I'm using Ansible to automate some configuration steps for my application VM, but having difficult to insert a new key-value to an existing json file on the remote host.
Say I have this json file:
{ "foo": "bar" }
And I want to insert a new key value pair to make the file become:
{ "foo": "bar", "hello": "world" }
Since json format is not line based, I'm excluding lineinfile
module from my options. Also, I would prefer not to use any external modules. Google keeps giving me examples to show how to read json file, but nothing about change json values and write them back to file. Really appreciate your help please!
Each key-value pair is separated by a comma, so the middle of a JSON lists as follows: "key" : "value", "key" : "value", "key": "value" . In the previous example, the first key-value pair is "first_name" : "Sammy" . JSON keys are on the left side of the colon.
Keys must be strings, and values must be a valid JSON data type: string. number.
A JSON database makes it possible to store data as JSON and provide it to applications in other forms. For example, it can operate as an in-memory key-value store for applications that just need quick and easy access. Or, indexing and querying can make JSON data appear as a table.
To get the key and value from a JSON string you can use the JSON. parse() method it will convert the JSON string to a JSON object and you can easily get key and value.
since the file is of json format, you could import the file to a variable, append the extra key:value pairs you want, and then write back to the filesystem.
here is a way to do it:
--- - hosts: localhost connection: local gather_facts: false vars: tasks: - name: load var from file include_vars: file: /tmp/var.json name: imported_var - debug: var: imported_var - name: append more key/values set_fact: imported_var: "{{ imported_var | default([]) | combine({ 'hello': 'world' }) }}" - debug: var: imported_var - name: write var to file copy: content: "{{ imported_var | to_nice_json }}" dest: /tmp/final.json
UPDATE:
as OP updated, the code should work towards remote host, in this case we cant use included_vars
or lookups. We could use the slurp
module.
NEW code for remote hosts:
--- - hosts: greenhat # connection: local gather_facts: false vars: tasks: - name: load var from file slurp: src: /tmp/var.json register: imported_var - debug: msg: "{{ imported_var.content|b64decode|from_json }}" - name: append more key/values set_fact: imported_var: "{{ imported_var.content|b64decode|from_json | default([]) | combine({ 'hello': 'world' }) }}" - debug: var: imported_var - name: write var to file copy: content: "{{ imported_var | to_nice_json }}" dest: /tmp/final.json
hope it helps
ilias-sp's solution is great!
In my case, it lacked the case when we may have to create a base json file. So I had to add this task in the beginning of the play:
- name: Ensure json file exists copy: content: "{}" dest: /tmp/var.json force: false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With