Search code examples
arraysjsonapache-nifitransformationjolt

Nifi: Change the same values of all elements in an array (e.g. test="nio" => test=0)


Edit1: Any number of new attributes with the same name can be added, for which the value is also to be changed. Therefore, several attributes with the same name and the same value can occur, which must all be exchanged. Therefore it should be dynamic.

I can no longer get on in Nifi at the following point. I would like to change the values of certain attributes in an array on the same basis. In my case, for example, the following change would be desired:

test="nio" => test=0

test="io" => test=1

My first guess is to implement this with JOLT, but I currently lack any approach in this regard.

Input:

{
  "counterTop": {
    "loaf1": [
      {
        "type": "white",
        "unit": "mm",
        "test": "nio"
      },
      {
        "type": "black",
        "unit": "cm",
        "test": "io"
      },
      {
        "type": "black123",
        "unit": "mm",
        "test": "io"
      }
    ]
  }
}

Expected output:

{
  "counterTop": {
    "loaf1": [
      {
        "type": "white",
        "unit": "mm",
        "test": "0"
      },
      {
        "type": "black",
        "unit": "cm",
        "test": "1"
      },
      {
        "type": "black123",
        "unit": "mm",
        "test": "1"
      }
    ]
  }
}

Does anyone here have a solution? Thanks in advance!


Solution

  • You can divide upto the innermost by roaming through "*" wildcards firstly, then conquer by combining within counterTop.loaf1[&..] such as

    [
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "*": {
                "*": "counterTop.loaf1[&1].&",
                "test": {
                  "nio": {
                    "@(2,&1)": { "*": { "#0": "counterTop.loaf1[&].&4" } }
                  },
                  "io": {
                    "@(2,&1)": { "*": { "#1": "counterTop.loaf1[&].&4" } }
                  }
                }
              }
            }
          }
        }
      }
    ]
    

    where the rightmost .&4 represents going 4 level up in order to reach the key test, and the rightmost .& represents the values for the rest of the keys.

    Edit : Considering your last case with multiple elements, you can prefer using the following instead of the above one as a generic case

    [
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "*": {
                "*": "loaf1[&1].&",
                "test": {
                  "nio": {
                    "@(2,&1)": { "*": { "#0": "&4" } }
                  },
                  "io": {
                    "@(2,&1)": { "*": { "#1": "&4" } }
                  }
                }
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "test": {
            "*": "counterTop.loaf1[&].&1",
            "@(1,loaf1)": "counterTop.loaf1"
          }
        }
      }
    ]