Search code examples
jsonmultidimensional-arrayapache-nifitransformationjolt

Conditional Jolt spec for nested array


I am trying to write Jolt spec for the following input. I need to populate the primaryEmail field based on the condition if primary field is true in the emails array

[
  {
    "uid": "1234mark",
    "name": "mark",
    "userName": "markw",
    "displayName": "Mark W",
    "emails": [
      {
        "primary": false,
        "value": "mark@gmail.com"
      },
      {
        "primary": true,
        "value": "mark@hotmail.com"
      }
    ]
  },
  {
    "uid": "9876steve",
    "name": "steve",
    "userName": "stevew",
    "displayName": "Steve W",
    "emails": [
      {
        "primary": false,
        "value": "steve@gmail.com"
      },
      {
        "primary": true,
        "value": "steve@hotmail.com"
      }
    ]
  }
]

The desired output is

[
  {
    "user": {
      "externalId": "1234mark",
      "name": "mark",
      "userName": "markw",
      "displayName": "Mark W",
      "primaryEmail": "mark@hotmail.com"
    }
  },
  {
    "user": {
      "externalId": "9876steve",
      "name": "steve",
      "userName": "stevew",
      "displayName": "Steve W",
      "primaryEmail": "steve@hotmail.com"
    }
  }
]

But I get the following incorrect output since I am not able to populate the primaryEmail field conditionally properly.

[
  {
    "user": {
      "externalId": "1234mark",
      "name": "mark",
      "userName": "markw",
      "displayName": "Mark W"
    }
  },
  {
    "user": {
      "externalId": "9876steve",
      "name": "steve",
      "userName": "stevew",
      "displayName": "Steve W"
    }
  }
]

The spec I have created is the following

[
  {
    "operation": "shift",
    "spec": {
      "*": {
        "uid": "[&1].user.externalId",
        "name": "[&1].user.name",
        "userName": "[&1].user.userName",
        "displayName": "[&1].user.displayName",
        "title": "[&1].user.title",
        "emails": {
          "*": {
            "primary": {
              "true": {
                "@(2,value)": "primaryEmail"
              }
            }
          }
        }
      }
    }
  }
]

Could someone please help with this query. Thanks.


Solution

  • What you need is to go 5 levels the three up from the innermost object while adding an extra node called user such as

    [
      {
        "operation": "shift",
        "spec": {
          "*": {
            "uid": "[&1].user.externalId",
            "*": "[&1].user.&", // the attributes except for "uid" and "emails" array
            "emails": {
              "*": {
                "primary": {
                  "true": {
                    "@(2,value)": "[&5].user.&2Email" // replicate literal "primary" by using &2
                  }
                }
              }
            }
          }
        }
      }
    ]
    

    the demo on the site http://jolt-demo.appspot.com/ is

    enter image description here