Search code examples
jsonjolt

jolt transformation for EDI data


I'm looking to transform EDI 834 data (in json) using jolt. Basically, I'd like the internal array of HD-2300_loop 'drive' the output. Here's the (simplified) input:

{
  "INS-2000_loop": [
    {
      "INS_01": "Y",
      "INS_02": "18",
      "INS_05": "A",
      "INS_06": "D"
    },
    {
      "REF_01": "0F",
      "REF_02": "11111111"
    },
    {
      "REF_01": "1L",
      "REF_02": "22222"
    },
    {
      "NM1-2100A_loop": [
        {
          "NM1_01": "IL",
          "NM1_02": "1",
          "NM1_03": "HOMER",
          "NM1_04": "SIMPSON",
          "NM1_05": "J"
        },
        {
          "PER_01": "IP",
          "PER_03": "CP",
          "PER_04": "4444444444"
        },
        {
          "PER_01": "IP",
          "PER_03": "HP",
          "PER_04": "5555555555"
        },
        {
          "N3_01": "742 Evergreen Terrace"
        },
        {
          "N4_01": "Springfield",
          "N4_02": "XX",
          "N4_03": "66666",
          "N4_05": "YY",
          "N4_06": "MY_COUNTY"
        },
        {
          "DMG_01": "D8",
          "DMG_02": "19560512",
          "DMG_03": "M"
        }
      ]
    },
    {
      "HD-2300_loop": [
        {
          "HD_01": "001",
          "HD_03": "HMO",
          "HD_04": "000-000-000",
          "HD_05": "IND"
        },
        {
          "DTP_01": "348",
          "DTP_02": "D8",
          "DTP_03": "20240101"
        }
      ]
    },
    {
      "HD-2300_loop": [
        {
          "HD_01": "001",
          "HD_03": "HMO",
          "HD_04": "000-010-000",
          "HD_05": "IND"
        },
        {
          "DTP_01": "348",
          "DTP_02": "D8",
          "DTP_03": "20231101"
        },
        {
          "DTP_01": "349",
          "DTP_02": "D8",
          "DTP_03": "20231231"
        }
      ]
    }
  ]
}

And here's my desired output (annotated) - an array with same size as number of HD-2300_loop objects in the input:

[
  {
    //these elements repeat
    "SUBSCRIBER_IND": "Y", //INS_01
    "RELATIONSHIP_CODE": "18", //INS_02
    "SUBSCRIBER_ID": "11111111", //[REF_01 == 'OF']REF_02
    "GROUP_ID": "22222", //[REF_01 == '1L']REF_02
    "MEMBER_NAME_FIRST": "HOMER", //NM1-2100A_loop/NM1_03
    "MEMBER_NAME_LAST": "SIMPSON", //NM1-2100A_loop/NM1_04
    "MEMBER_NAME_MI": "J", //NM1-2100A_loop/NM1_05
    "MEMBER_CONTACT_CP": "4444444444", //NM1-2100A_loop[PER_03 = 'CP']/PER_04
    "MEMBER_CONTACT_HP": "5555555555", //NM1-2100A_loop[PER_03 = 'HP']/PER_04
    "MEMBER_ADDR_STREET1": "742 Evergreen Terrace", //NM1-2100A_loop/N3_01
    "MEMBER_ADDR_CITY": "Springfield", //NM1-2100A_loop/N4_01
    "MEMBER_ADDR_STATE": "XX", //NM1-2100A_loop/N4_02
    "MEMBER_ADDR_ZIP": "66666", //NM1-2100A_loop/N4_03
    "MEMBER_ADDR_COUNTY": "MY_COUNTY", //NM1-2100A_loop/N4_06
    "MEMBER_DOB": "19560512", //NM1-2100A_loop/DMG_02
    "MEMBER_GENDER": "M", //NM1-2100A_loop/DMG_03
                          //these elements from the 'driving' HD-2300_loop
    "COVERAGE_START": "20240101", //HD-2300_loop[DTP_01 = '348']/DTP_03
    "COVERAGE_END": null, //HD-2300_loop[DTP_01 = '349']/DTP_03 (may be absent)
    "COVERAGE_TYPE": "IND", //HD-2300_loop/HD_05
    "COVERAGE_PLAN_TYPE": "HMO", //HD-2300_loop/HD_03
    "COVERAGE_PLAN_ID": "000-000-000" //HD-2300_loop/HD_04
  },
  {
    "SUBSCRIBER_IND": "Y",
    "RELATIONSHIP_CODE": "18",
    "SUBSCRIBER_ID": "11111111",
    "GROUP_ID": "22222",
    "MEMBER_NAME_FIRST": "HOMER",
    "MEMBER_NAME_LAST": "SIMPSON",
    "MEMBER_NAME_MI": "J",
    "MEMBER_CONTACT_CP": "4444444444",
    "MEMBER_CONTACT_HP": "5555555555",
    "MEMBER_ADDR_STREET1": "742 Evergreen Terrace",
    "MEMBER_ADDR_CITY": "Springfield",
    "MEMBER_ADDR_STATE": "XX",
    "MEMBER_ADDR_ZIP": "66666",
    "MEMBER_ADDR_COUNTY": "MY_COUNTY",
    "MEMBER_DOB": "19560512",
    "MEMBER_GENDER": "M",
    "COVERAGE_START": "20231101",
    "COVERAGE_END": "20231231",
    "COVERAGE_TYPE": "IND",
    "COVERAGE_PLAN_TYPE": "HMO",
    "COVERAGE_PLAN_ID": "000-010-000"
  }
]

Solution

  • You can try the below spec:

    [
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              //Create coverage group for each coverage option
              "HD-2300_loop": {
                "*": {
                  "HD_05": "&4[&3].Coverage.COVERAGE_TYPE",
                  "HD_03": "&4[&3].Coverage.COVERAGE_PLAN_TYPE",
                  "HD_04": "&4[&3].Coverage.COVERAGE_PLAN_ID",
                  "DTP_01": {
                    "348": {
                      "@(2,DTP_03)": "&6[&5].Coverage.COVERAGE_START"
                    },
                    "349": {
                      "@(2,DTP_03)": "&6[&5].Coverage.COVERAGE_END" //same relative path as COVERAGE_START
                    }
                  }
                }
              },
              //Gather rest of information and store under Common parent node
              "INS_01": "Common.SUBSCRIBER_IND",
              "INS_02": "Common.RELATIONSHIP_CODE",
              "REF_01": {
                "0F": {
                  "@(2,REF_02)": "Common.SUBSCRIBER_ID"
                },
                "1L": {
                  "@(2,REF_02)": "Common.PLAN_ID"
                }
              },
              "NM1-2100A_loop": {
                "*": {
                  "NM1_03": "Common.MEMBER_NAME_FIRST",
                  "NM1_04": "Common.MEMBER_NAME_LAST",
                  "NM1_05": "Common.MEMBER_NAME_MI",
                  "PER_03": {
                    "*": {
                      "@(2,PER_04)": "Common.MEMBER_CONTACT_&1"
                    }
                  },
                  "N3_01": "Common.MEMBER_ADDR_STREET1",
                  "N4_01": "Common.MEMBER_ADDR_CITY",
                  "N4_02": "Common.MEMBER_ADDR_STATE",
                  "N4_03": "Common.MEMBER_ADDR_ZIP",
                  "N4_06": "Common.MEMBER_ADDR_COUNTY",
                  "DMG_02": "Common.MEMBER_DOB",
                  "DMG_03": "Common.MEMBER_GENDER"
                }
              }
            }
          }
        }
      }
      ,
      {
        //remove null elements from the INS-2000_loop
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "Coverage": "Coverage.[]"
            }
          },
          "Common": "&"
        }
      }
      ,
      {
        //bucket each common attribute into each coverage element
        "operation": "shift",
        "spec": {
          "Coverage": {
            "*": {
              "@(2,Common)": {
                "*": "[&2].&"
              },
              "*": "[&1].&"
            }
          }
        }
      }/**/
     ]