Closed deepakbshetty closed 4 months ago
Hi @deepakbshetty,
If I understand correctly, you are attempting to entirely replace the contents of an Array/List at a specific node in a JSON document. While this is possible with the tools provided by yamlpath, yaml-set
is not the correct tool for such a non-scalar change; use yaml-merge
, instead.
As documented, the yaml-set
command is designed to handle only atomic changes to scalar values. In this context, the behavior you see is correct albeit unexpected. What you have really done is to instruct yaml-set
to replace an Array/List with a scalar String (which happens to look like a JSON Array but really is not given how you've attempted to use it).
I don't see what your actual desired outcome is, so I'll make something up under the assumption that you wish to entirely overwrite a specific Array/List in your target JSON document. Suppose you want to transform your test.json document such that "registry-mirrors" is an array with the absolute values:
This is very simple using yaml-merge, as demonstrated here:
$ python3 --version
Python 3.12.2
$ yaml-merge --version
yaml-merge 3.8.2
$ cat test.json
{ "registry-mirrors" : ["value1", "value2" ] }
$ echo '{ "registry-mirrors" : [ "item1", "item2" ] }' | yaml-merge --arrays right test.json -
{"registry-mirrors": ["item1", "item2"]}
As you can see, because of the --arrays right
option, the command entirely replaces the "registry-mirrors" Array/List with the contents from STDIN (which is to the "right" of test.json in the command-line). Were your document more complex, you'd see that indeed, only the "registry-mirrors" Array/List was affected despite the STDIN document containing only replacement content for "registry-mirrors".
The yaml-merge
command is vastly more capable than yaml-set
when it comes to non-scalar nodes.
Please let me know if your use-case is more complex than what is presented here and you need a more specific example. I'll keep this ticket open for a few days or until I hear back from you, whichever comes first.
Hi @wwkimball
Thank you. Your assumption is correct. I now see fitment of yaml-merge for non scalar values. I hope yaml-merge supports merge from stdin if keys have deep nesting?
Happy for the query to be closed post response.
Indeed; the command supports any depth you could need. It also allows per-node configuration (different merging rules for different nodes) for complex merging. You can also write a shallow document and use the --mergeat argument to tell the command to merge the right-hand document anywhere you like within the left-hand document.
Please visit the Wiki for a deep dive into these capabilities.
What we are trying to do - Update list of values in JSON test.json
{ "registry-mirrors" : ["value1", "value2" ] }
Issue: We are able to use yaml-set with individual index and update values however unable to update all values at once.
Works: yaml-set --change .registry-mirrors[0] --value value1 test.json yaml-set --change .registry-mirrors[1] --value value2 test.json
Does not work - Updating in bulk and results in double quoted string yaml-set --change .registry-mirrors --value ["value1", "value2" ] test.json { "registry-mirrors" : "["value1", "value2" ]" }` @wwkimball Would appreciate your inputs on achieving this.