Search code examples
jsonjolt

Check for not null condition and assign a value to that field in an array using Jolt Spec


Input JSON1 :

{
  "task": {
    "external_id": "2023-03-22-13-15-18-184000",
    "way_points": [
      {
        "address": "Warminster Road",
        "position": 1,
        "eta": null
      },
      {
        "address": "7 John Rennie Close",
        "position": 2,
        "eta": "2023-03-22T13:33:54.827Z"
      }
    ]
  },
  "webhook_type": "driver_on_the_way",
  "merchant_id": 60470
}

Output JSON1:

{
  "shipper" : 60470,
  "shipmentId" : "externalId",
  "messages" : [ {
    "eta" : "2023-03-22T13:33:54.827Z",
    "messageType" : "STOP_ETA_UPDATE",
    "message" : "driver_on_the_way"
  } ]
}

Input JSON2 :

{
  "task": {
    "external_id": "2023-03-22-13-15-18-184000",
    "way_points": [
      {
        "address": "Warminster Road",
        "position": 1,
        "eta": null
      }
    ]
  },
  "webhook_type": "driver_on_the_way",
  "merchant_id": 60470
}

Output JSON2:

{
  "shipper" : 60470,
  "shipmentId" : "externalId",
  "messages" : [ {
    "eta" : "2023-03-22T13:33:54.827Z",
    "messageType" : "TRACKING_UPDATE",
    "message" : "driver_on_the_way"
  } ]
}

Description: There are 2 positions : 1 and 2 in the way_points list. There is a possibility that only position : 1 can be present or both positions : 1 and 2 can be present. Now, if position : 2 is present and eta is not null, then messageType = 'STOP_ETA_UPDATE' but if position : 2 is not present then messageType = 'TRACKING_UPDATE'

Jolt Spec:

[
  {
    "operation": "shift",
    "spec": {
      "task": {
        "way_points": {
          "*": {
            "position": {
              "2": {
                "eta": {
                  "|null": null,
                  "#TRACKING_UPDATE": "messageType1",
                  "*": {
                    "#STOP_ETA_UPDATE": "messageType1"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
]

Solution

  • You can use the following lastElement function to grab the object labeled with the highest position ( as there might exist 1 or 2) after sorting them based on those labels such as

    [
      { // determine the cases for the conditional that will be used in the next step
        "operation": "modify-overwrite-beta",
        "spec": {
          "task": {
            "way_points": {
              "*": {
                "eta_": ["=isNull(@(1,eta))", "Notnull"], // if "eta" is not null, then assign "Notnull"
                "new_val": "=concat(@(1,position),'_',@(1,eta_))"
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "merchant_id": "shipper",
          "#externalId": "shipmentId",
          "task": {
            "way_points": {
              "*": {
                "new_val": {
                  "2_Notnull": {
                    "#STOP_ETA_UPDATE": "&5.@3,position.messageType",
                    "@2,eta": "&5.@3,position.eta"
                  },
                  "*": {
                    "#TRACKING_UPDATE": "&5.@3,position.messageType",
                    "@2,eta": "&5.@3,position.eta"
                  }
                }
              }
            }
          }
        }
      },
      {
        "operation": "sort"
      },
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "task": {
            "*": "messages[]"
          }
        }
      },
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "messages": "=lastElement(@(1,&))"
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "messages": "&[]"
        }
      }
    ]