'Replace value in nested YAML with Jsonnet
Let's say I have the following YAML and I'd like to replace 'samsung' with 'apple' how do I do this in jsonnet? I could not find any way doing this and I'm searching for the solution since hours.
products:
- smartphones:
- samsung
computers:
- hp
Solution 1:[1]
You should more clearly specify the "nature" of your (main) object schema, to better craft possible answers (i.e.: do you already know the specific field you want to replace arrays' entries?, Are there more deeply nested objects+arrays?, etc)
Copying below 3 possible answers, all manifesting the same JSON output (also valid YAML, as YAML is a language superset of JSON), in order of complexity (and generalization):
NB: input YAML is loaded from foo.yaml existing file.
1) Hack~ish, brute-force approach, dumb string replace :P
local FROM = 'samsung';
local TO = 'apple';
// Load foo.yaml as (just) a string
local yamlStr = importstr 'foo.yaml';
// NB: hack~ish, brute-force approach, dumb string replace :P
std.parseYaml(std.strReplace(yamlStr, FROM, TO))
2) Replace entry in already known, specific (main object) field
local FROM = 'samsung';
local TO = 'apple';
// Load foo.yaml as jsonnet object
local yaml = std.parseYaml(importstr 'foo.yaml');
// Replace array entries matching `from` with `to`
local replaceElem(array, from, to) = [
if entry == from then to else from
for entry in array
];
// NB: Replace entry in already known, specific (main object) field
{
products: [
product {
smartphones: replaceElem(super.smartphones, FROM, TO),
}
for product in yaml.products
],
}
3) Recurse the main object, looking for strings to replace
local FROM = 'samsung';
local TO = 'apple';
// Load foo.yaml as jsonnet object
local yaml = std.parseYaml(importstr 'foo.yaml');
// NB: Recurse the main object, looking for strings to replace
local recurseReplace(any, from, to) = (
{
object: function(x) { [k]: recurseReplace(x[k], from, to) for k in std.objectFields(x) },
array: function(x) [recurseReplace(e, from, to) for e in x],
string: function(x) if x == from then to else x,
}[std.type(any)](any)
);
recurseReplace(yaml, FROM, TO)
FTR manifested output, same for all three above
{
"products": [
{
"computers": [
"hp"
],
"smartphones": [
"apple"
]
}
]
}
FTR manifested output, piped thru yq -PI2 e . -
products:
- computers:
- hp
smartphones:
- apple
I personally prefer 3) above, as it's the most generic for any object depth and schema.
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 | jjo |
