0

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
newduino
  • 179
  • 1
  • 6
  • 16

1 Answers1

0

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.

jjo
  • 2,595
  • 1
  • 8
  • 16