Search code examples
jsonjoltdata-transform

Nested loop to several arrays with jolt library


In input, I have a list of persons. Each person has several addresses and roles on contract. Example :

  • Person #001 has :
    • two addresses secondary residence and tax address ;
    • two roles co-subscriber and insured
  • Person #002 has :
    • two addresses (i) principal residence and tax address ;
    • three roles co-subscriber, insured and premium payer.
{
  "personnes": [
    {
      "refExternePersonne": "BGHT34271",
      "isPersonnePhysique": true,
      "rolesContrat": [
        "CO_SOUSCRIPTEUR",
        "ASSURE"
      ],
      "adresses": [
        {
          "typeAdresse": "RESIDENCE_SECONDAIRE"
        },
        {
          "typeAdresse": "FISCALE"
        }
      ]
    },
    {
      "refExternePersonne": "BGHT34272",
      "isPersonnePhysique": false,
      "rolesContrat": [
        "SOUSCRIPTEUR",
        "PAYEUR_PRIMES",
        "ASSURE"
      ],
      "adresses": [
        {
          "typeAdresse": "FISCALE"
        },
        {
          "typeAdresse": "CORRESPONDANCE"
        }
      ]
    }
  ]
}

Why my spec is incorrect?

[
  {
    "operation": "shift",
    "spec": {
      "personnes": {
        "*": {
          "refExternePersonne": "parties[&1].partyRef",
          "rolesContrat": {
            "*": {
              "SOUSCRIPTEUR": {
                "@(3,isPersonnePhysique)": {
                  "true": {
                    "#%phys%": "tickets.processId"
                  },
                  "false": {
                    "#%morale%": "tickets.processId"
                  }
                },
                "@(3,refExternePersonne)": "policies.subscribers[].partyRef",
                "@(3,idPersonne)": "policies.subscribers[].partyId",
                "@(3,adresses)": "policies.subscribers[].addressesTemp"
              },
              "CO_SOUSCRIPTEUR": {
                "@(3,refExternePersonne)": "policies.cosubscribers[].partyRef",
                "@(3,idPersonne)": "policies.cosubscribers[].partyId",
                "@(3,adresses)": "policies.cosubscribers[].addressesTemp"
              },
              "ASSURE": {
                "@(3,refExternePersonne)": "policies.insured[].partyRef",
                "@(3,idPersonne)": "policies.insured[].partyId",
                "@(3,adresses)": "policies.insured[].addressesTemp"
              }
            }
          }
        }
      }
    }
  }
]

I try to group people with their addresses according to their role on the contract:

  • people with the subscriber role are grouped in policies.subscribers[]
  • insured role => policies.insured[]
  • role co-subscriber => policies.cosubscribers[]

Expected output:

{
  "parties": [
    {
      "partyRef": "BGHT34271"
    },
    {
      "partyRef": "BGHT34272"
    }
  ],
  "policies": {
    "cosubscribers": [
      {
        "partyRef": "BGHT34271",
        "addressesTemp": [
          {
            "typeAdresse": "RESIDENCE_SECONDAIRE"
          },
          {
            "typeAdresse": "FISCALE"
          }
        ]
      }
    ],
    "insured": [
      {
        "partyRef": "BGHT34271",
        "addressesTemp": [
          {
            "typeAdresse": "RESIDENCE_SECONDAIRE"
          },
          {
            "typeAdresse": "FISCALE"
          }
        ]
      },
      {
        "partyRef": "BGHT34272",
        "addressesTemp": [
          {
            "typeAdresse": "FISCALE"
          },
          {
            "typeAdresse": "CORRESPONDANCE"
          }
        ]
      }
    ],
    "subscribers": [
      {
        "partyRef": "BGHT34272",
        "addressesTemp": [
          {
            "typeAdresse": "FISCALE"
          },
          {
            "typeAdresse": "CORRESPONDANCE"
          }
        ]
      }
    ]
  },
  "tickets": {
    "processId": "%morale%"
  }
}

Solution

  • I think that you'd better thinking with the logic of looping such as

    [
      { // grouping by elements of "rolesContrat" 
        // and then by "refExternePersonne" values phase
        "operation": "shift",
        "spec": {
          "personnes": {
            "*": {
              "refExternePersonne": "parties[&1].partyRef",
              "rolesContrat": {
                "*": {
                  "*": {
                    "@3,refExternePersonne": "&.&2.partyRef",
                    "@3,adresses": "&.&2.addressesTemp",
                    "@3,isPersonnePhysique": "&.&2.PP"
                  }
                }
              }
            }
          }
        }
      },
      { // renaming phase
        "operation": "shift",
        "spec": {
          "parties": "&",
          "CO_SOU*": {
            "*": {
              "*": "policies.cosubscribers[#2].&"
            }
          },
          "ASSURE": {
            "*": {
              "*": "policies.insured[#2].&"
            }
          },
          "SOUS*": {
            "*": {
              "PP": {
                "true": {
                  "#%phys%": "tickets.processId"
                },
                "false": {
                  "#%morale%": "tickets.processId"
                }
              },
              "*": "policies.subscribers[#2].&"
            }
          }
        }
      },
      { // phase of removing the extra attribute which is "PP" 
        "operation": "remove",
        "spec": {
          "*": {
            "*": {
              "*": {
                "PP": ""
              }
            }
          }
        }
      }
    ]