Search code examples
jsontransformapache-nifijolt

JSON JOLT Transform


I need to transform given input JSON to desired output json using jolt transform

This is my input JSON

{
  "fragmented": true,
  "nodeIp": "192.168.0.20",
  "requestId": "35daa014-d995-47ab-885b-0ce5ef24a214",
  "nodeId": "143898594",
  "timestamp": 1717413230106,
  "requestTimestamp": 1717413185926,
  "data": {
    "storage_controller": [
      {
        "ctlr_status": "up",
        "ctlr_name": "Top Controller",
        "ctlr_ip_address": "192.168.0.21",
        "ctlr_force_trap": "Empty",
        "ctlr_service_tag": "FSHVH82",
        "ctlr_asset_tag": "",
        "index": "1",
        "ctlr_leader": 1,
        "ctlr_number": 1,
        "ctlr_model": "CT_SC4020"
      },
      {
        "ctlr_leader": 2,
        "ctlr_ip_address": "192.168.0.22",
        "ctlr_model": "CT_SC4020",
        "ctlr_service_tag": "FSHVH82",
        "index": "2",
        "ctlr_number": 2,
        "ctlr_status": "up",
        "ctlr_name": "Bottom Controller",
        "ctlr_force_trap": "Empty",
        "ctlr_asset_tag": ""
      }
    ],
    "storage_controller_temp": [
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 3,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 38,
        "ctlr_temp_name": "DIMM2",
        "index": "1.3"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 4,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 45,
        "ctlr_temp_name": "PCIe Zone Inlet",
        "index": "2.4"
      },
      {
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 40,
        "ctlr_temp_name": "CPU Outlet",
        "index": "2.6",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 6
      },
      {
        "ctlr_temp_current_c": 35,
        "ctlr_temp_name": "DIMM2",
        "index": "2.3",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 3,
        "ctlr_temp_status": "up"
      },
      {
        "ctlr_temp_current_c": 35,
        "ctlr_temp_name": "DIMM1",
        "index": "2.2",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 2,
        "ctlr_temp_status": "up"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 2,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 38,
        "ctlr_temp_name": "DIMM1",
        "index": "1.2"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 5,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 45,
        "ctlr_temp_name": "PCIe Zone Outlet",
        "index": "1.5"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 1,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 62,
        "ctlr_temp_name": "CPU One",
        "index": "1.1"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 6,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 43,
        "ctlr_temp_name": "CPU Outlet",
        "index": "1.6"
      },
      {
        "ctlr_temp_name": "BBU",
        "index": "1.7",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 7,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 32
      },
      {
        "ctlr_temp_number": 4,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 48,
        "ctlr_temp_name": "PCIe Zone Inlet",
        "index": "1.4",
        "ctlr_temp_force_trap": "Empty"
      },
      {
        "index": "2.5",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 5,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 41,
        "ctlr_temp_name": "PCIe Zone Outlet"
      },
      {
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 7,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 30,
        "ctlr_temp_name": "BBU",
        "index": "2.7"
      },
      {
        "ctlr_temp_name": "CPU One",
        "index": "2.1",
        "ctlr_temp_force_trap": "Empty",
        "ctlr_temp_number": 1,
        "ctlr_temp_status": "up",
        "ctlr_temp_current_c": 52
      }
    ]
  }
}

And this is output that I want to get

{
  "fragmented": true,
  "nodeIp": "192.168.0.20",
  "requestId": "3b93f973-0b88-4464-8208-8ff6dc27189d",
  "nodeId": "143898594",
  "timestamp": 1717078433124,
  "requestTimestamp": 1717078414005,
  "data": {
    "storage_controller": [
      {
        "ctlr_asset_tag": "",
        "ctlr_leader": 2,
        "ctlr_status": "up",
        "ctlr_ip_address": "192.168.0.22",
        "ctlr_force_trap": "Empty",
        "ctlr_service_tag": "FSHVH82",
        "ctlr_number": 2,
        "ctlr_name": "Bottom Controller",
        "ctlr_model": "CT_SC4020",
        "index": "2",
        "temp_sensors": [
          {
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 48,
            "ctlr_temp_name": "CPU One",
            "index": "2.1",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 1
          },
          {
            "index": "2.2",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 2,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 34,
            "ctlr_temp_name": "DIMM1"
          },
          {
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 34,
            "ctlr_temp_name": "DIMM2",
            "index": "2.3",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 3
          },
          {
            "ctlr_temp_name": "PCIe Zone Inlet",
            "index": "2.4",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 4,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 44
          },
          {
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 5,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 41,
            "ctlr_temp_name": "PCIe Zone Outlet",
            "index": "2.5"
          },
          {
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 6,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 40,
            "ctlr_temp_name": "CPU Outlet",
            "index": "2.6"
          },
          {
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 29,
            "ctlr_temp_name": "BBU",
            "index": "2.7",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 7
          },
          
        ]
      },
      {
        "ctlr_leader": 1,
        "ctlr_number": 1,
        "ctlr_status": "up",
        "ctlr_name": "Top Controller",
        "ctlr_ip_address": "192.168.0.21",
        "ctlr_force_trap": "Empty",
        "ctlr_model": "CT_SC4020",
        "ctlr_service_tag": "FSHVH82",
        "ctlr_asset_tag": "",
        "index": "1",
        "temp_sensors": [
          {
            "ctlr_temp_name": "CPU One",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 1,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 61,
            "index": "1.1",
            
          },
          {
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 2,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 38,
            "ctlr_temp_name": "DIMM1",
            "index": "1.2",
            
          },
          {
            "ctlr_temp_current_c": 37,
            "ctlr_temp_name": "DIMM2",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 3,
            "ctlr_temp_status": "up",
            "index": "1.3",
            
          },
          {
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 48,
            "ctlr_temp_name": "PCIe Zone Inlet",
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 4,
            "index": "1.4",
            
          },
          {
            "ctlr_temp_number": 5,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 45,
            "ctlr_temp_name": "PCIe Zone Outlet",
            "ctlr_temp_force_trap": "Empty",
            "index": "1.5",
            
          },
          {
            "ctlr_temp_number": 6,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 43,
            "ctlr_temp_name": "CPU Outlet",
            "ctlr_temp_force_trap": "Empty",
            "index": "1.7",
            
          },
          {
            "ctlr_temp_force_trap": "Empty",
            "ctlr_temp_number": 7,
            "ctlr_temp_status": "up",
            "ctlr_temp_current_c": 31,
            "ctlr_temp_name": "BBU",
            "index": "1.8",
            
          }
        ]
      }
    ]
  }
}

Each storage_controller has storage_controller_temp, storage_controller_temp has index key which value is string first number means to which storage_controller it belongs second number means which storage_controller_temp, so for example if storage_controller_temp has index "1.3" it means storage_controller_temp with ctlr_temp_number 3 belongs to storage_controller with ctlr_number 1

This is my jolt transform that i have tried

[
  {
    "operation": "shift",
    "spec": {
      "fragmented": "fragmented",
      "nodeIp": "nodeIp",
      "requestId": "requestId",
      "nodeId": "nodeId",
      "timestamp": "timestamp",
      "requestTimestamp": "requestTimestamp",
      "data": {
        "storage_controller": {
          "*": {
            "*": "data.storage_controller[&1].&",
            "@(2,storage_controller_temp)": {
              "*": {
                "@": "data.storage_controller[&3].temp_sensors[]"
              }
            }
          }
        }
      }
    }
  }
]

Solution

  • No need to match the outermost attributes one by one, just single

    "*":"&"
    

    pair handles the issue.

    Reference the following transformation specs for the complete case :

    [
      {
        "operation": "shift",
        "spec": {
          "*": "&",//the elements those are not beneath the "data" node
          "data": {
            "storage_controller": {
              "*": {
                "*": "&3.&2.@1,index.&"
              }
            },
            "storage_controller_temp": {
              "*": {
                "*": "&3.temp_sensors.@1,index.&1.&"
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "data": {
            "storage_controller": {
              "*": "&2.&1.&"
            },
            "temp_sensors": {
              "*.*": {
                "*": "&3.storage_controller.&(1,1).&2.&"//pick the 1st replacement of the dot separarted asterisks from 1 upper level by &(1,1)
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "data": {
            "storage_controller": {
              "*": {
                "*": "&2[#2].&",
                "temp_sensors": {
                  "*": {
                    "*": "&4[#4].&2[#2].&"
                  }
                }
              }
            }
          }
        }
      }
    ]