Data Transformations

Transforming data in Laminar

Running data transformations

Laminar's Lam Language is built entirely on top of JQ. Lam is run on each flow execution and is a JSON data transformation language that can support extremely complex conditional data transformations.

Data transformations access keys via dot notation and are able to reference data retrieved or transformed by previous flows in a workflow using the Global Workflow Object.

View a simple JQ example
# Remove some fields
.data | map(select(.value > 5))
View a complex JQ example
# Define safe_notes with robust checking for nested structures
def safe_notes:
  if .step_1.response.notes then
    [.step_1.response.notes[] | select(.custom_types != null and any(.custom_types[]; .note_custom_value == "0 = \"DELIVERY_SUCCESSFUL\""))]
  else
    []
  end;

# Extract image URLs from notes that have them
def images:
  if .step_1.response.notes then
    [.step_1.response.notes[] | 
     select(.upload_url? and .upload_url != "") | 
     {url: .upload_url, extension: .upload_extension}]
  else
    []
  end;

# Evaluate the detailed_event and contents of notes
if (.input.detailed_event == "completed" and (safe_notes | length > 0)) then
  # Output for confirmed completed status with valid delivery success note and image URLs
  {
    "lam.resolveThenExecute": {
      "lam.workflowId": 55,
      "lam.payload": {
        "images": (images),
        "data": {
            "TrackingNumber": .input.address_custom_data.barcode,
            "ScanLatitude": .step_1.response.visited_lat,
            "ScanLongitude": .step_1.response.visited_lng,
        }
      },
      "lam.result": {}
    }
  }
elif (.input.detailed_event == "completed" and (safe_notes | length == 0)) or .input.detailed_event == "skipped" or .input.detailed_event == "failed" then
  # Output for delivery issues or no valid delivery success note found
  {
    "WS_Key": "..",
    "WSKeyLevel": "Carrier",
    "CarrierId": 10204,
    "TrackingNumber": .input.address_custom_data.barcode,
    "StartDate": (now | strflocaltime("%Y-%m-%dT%H:%M:%S")),
    "EndDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
    "TrackingInfo": {
      "EstimatedDeliveryDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
      "DeliveryDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
      "Event": {
        "ScanDateTime": (now | strflocaltime("%Y-%m-%dT%H:%M:%S")),
        "Status": "DeliveryException",
        "Description": "Exception occurred during delivery",
        "AlternateLanguageCode": "English",
        "ScanCountry": "CA",
        "ScanState": "ON",
        "ScanCity": "...",
        "ScanPostal": "..."
      },
      "PerformanceState": 0
    },
    "UpdateTrackingInfoShipmentLevel": true
  }
elif .input.detailed_event == "loaded" then
  # Output for 'loaded' status
  {
    "WS_Key": "...",
    "WSKeyLevel": "Carrier",
    "CarrierId": 10204,
    "TrackingNumber": .input.address_custom_data.barcode,
    "StartDate": (now | strflocaltime("%Y-%m-%dT%H:%M:%S")),
    "EndDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
    "TrackingInfo": {
      "EstimatedDeliveryDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
      "DeliveryDate": (now + 86400 | strflocaltime("%Y-%m-%dT%H:%M:%S")),
      "Event": {
        "ScanDateTime": (now | strflocaltime("%Y-%m-%dT%H:%M:%S")),
        "Status": "OutForDelivery",
        "Description": "Package is out for delivery",
        "AlternateLanguageCode": "English",
        "ScanCountry": "CA",
        "ScanState": "ON",
        "ScanCity": "...",
        "ScanPostal": "..."
      },
      "PerformanceState": 0
    },
    "UpdateTrackingInfoShipmentLevel": true
  }
else
  { "lam.exit": true }
end

Invoking Laminar Keywords

Having a data transformation output one of the specified Laminar Keywords allows for more complex control flow logic to take place.

This is done by formatting the output in a way that is recognizable to the Laminar system as specified by the Laminar Keywords.

.input |
if ((.activity_type == "route-destination-status" or
     .activity_type == "update-destinations") and
    (.detailed_event? | tostring | test("skipped|failed|completed|loaded")) and
    (.order_id | length > 0))
then
{
  "lam.resolveThenExecute": {
    "lam.workflowId": 60,
    "lam.payload": .,
    "lam.result": { "status": "OK" }
  }
}
else 
    { "lam.exit": true } 
end

Last updated