Jolt Transform Nested Grouping - json

I have a JSON that has this flat structure:
[{
"PK": "1111",
"SOURCE_DB": "Oracle",
"CONTACT_TYPE": "Phone",
"CONTACT_SUBTYPE": "Work",
"EMAIL": null
"PHONE_COUNTRY_CODE": "44",
"PHONE_NUMBER": "12345678",
"PHONE_EXT": "907643",
"STATUS": "Active"
}, {
"PK": "1111",
"SOURCE_DB": "Oracle",
"CONTACT_TYPE": "Phone",
"CONTACT_SUBTYPE": "Home",
"EMAIL": null
"PHONE_COUNTRY_CODE": "353",
"PHONE_NUMBER": "87654321",
"PHONE_EXT": null,
"STATUS": "Active"
}, {
"PK": "1111",
"SOURCE_DB": "",
"CONTACT_TYPE": "Email",
"CONTACT_SUBTYPE": "Personal",
"EMAIL": "me#mail.com"
"PHONE_COUNTRY_CODE": null,
"PHONE_NUMBER": null,
"PHONE_EXT": null,
"STATUS": "Active"
},
{
"PK": "2222",
"SOURCE_DB": "DB2",
"CONTACT_TYPE": "Phone",
"CONTACT_SUBTYPE": "Home",
"EMAIL": null
"PHONE_COUNTRY_CODE": "44",
"PHONE_NUMBER": "98761234",
"PHONE_EXT": null,
"STATUS": "Inactive"
}, {
"PK": "2222",
"SOURCE_DB": "DB2",
"CONTACT_TYPE": "Email",
"CONTACT_SUBTYPE": "Work",
"EMAIL": "you#mail.co.uk"
"PHONE_COUNTRY_CODE": null,
"PHONE_NUMBER": null,
"PHONE_EXT": null,
"STATUS": "Active"
}
]
Then, I want to group them, first by Key (PK), then within each entry, ContactMethods will be grouped together. This is the output:
{
"Accounts": [{
"Reference": {
"Key": "1111",
"System": "Oracle"
},
"ContactMethods": {
"Phone": [{
"Subtype": "Work",
"CountryCode": "44",
"Number": "12345678",
"Extension": "907643",
"Active": true
}, {
"Subtype": "Home",
"CountryCode": "353",
"Number": "87654321",
"Extension": null,
"Active": true
}
],
"Email": [{
"Subtype": "Personal",
"EmailAddress": "my#mail.com",
"Active": true
}
]
}
}, {
"Reference": {
"Key": "2222",
"System": "DB2"
},
"ContactMethods": {
"Phone": [{
"Subtype": "Home",
"CountryCode": "44",
"Number": "98761234",
"Extension": null,
"Active": false
}
],
"Email": [{
"Subtype": "Work",
"EmailAddress": "you#mail.co.uk",
"Active": true
}
]
}
}
]
}
I am able to group this by PK, but I am having difficulty on the second part, on how to do the grouping within the nested structure. Can you show a sample spec and put some explanation?

Possible but really convoluted / verbose. This is pushing the bounds of what should be done with Jolt.
One pivot and some remapping is maintainable, but this is complicated enough that it will be very hard to debug if something goes wrong / you data is weird.
Requires 5 steps. Two to fix STATUS from a string to a boolean. Two to pivot and sub-pivot the data. And the last one to put everything in the right final place.
I recommend examine each step examine each step in it's own tab/copy of the Jolt demo site to see / grok what each step is doing.
Spec
[
{
// ninja in a true and false value so that
// Status "Active" / "Inactive" can be "mapped" to booleans
"operation": "default",
"spec": {
"*": {
"FALSE": false,
"TRUE": true
}
}
},
{
// fix STATUS
"operation": "shift",
"spec": {
"*": {
//
"STATUS": {
// Match "Active" as make STATUS be true
"Active": {
"#(2,TRUE)": "[&3].STATUS"
},
// Everything else set to false
"*": {
"#(2,FALSE)": "[&3].STATUS"
}
},
// match and discard TRUE and FALSE
"TRUE|FALSE": null,
// pass everything else thru
"*": "[&1].&"
}
}
},
{
// now, group by PK value
"operation": "shift",
"spec": {
// top level array
"*": {
"PK": {
"*": { // match any value of PK
// go back up and grab the whole block and write
// it to the ouput where the key, is the value of PK
"#2": "&1[]"
}
}
}
}
},
{
// sub group by CONTACT_TYPE, with the complication of
// pulling one entry off to serve as the "Reference"
"operation": "shift",
"spec": {
"*": { // pk value
"0": { // special case the Zeroth item so that
// we can pull off once copy to serve as the
// Reference
"#": "&2.Reference",
// sub group by CONTACT_TYPE
"CONTACT_TYPE": {
"*": {
"#2": "&4.ContactMethods.&1[]"
}
}
},
"*": { // all the rest of the array indicies
// sub group by CONTACT_TYPE
"CONTACT_TYPE": {
"*": {
"#2": "&4.ContactMethods.&1[]"
}
}
}
}
}
},
{
// Data fixing and Grouping done, now put everything
// in its final place
"operation": "shift",
"spec": {
"*": { // top level pk
"Reference": {
"PK": "Accounts[#3].Reference.Key",
"SOURCE_DB": "Accounts[#3].Reference.System"
},
"ContactMethods": {
"Phone": {
"*": {
"CONTACT_SUBTYPE": "Accounts[#5].ContactMethods.Phone[&1].Subtype",
"PHONE_COUNTRY_CODE": "Accounts[#5].ContactMethods.Phone[&1].CountryCode",
"PHONE_NUMBER": "Accounts[#5].ContactMethods.Phone[&1].Number",
"PHONE_EXT": "Accounts[#5].ContactMethods.Phone[&1].Extension",
"STATUS": "Accounts[#5].ContactMethods.Phone[&1].Active"
}
},
"Email": {
"*": {
"CONTACT_SUBTYPE": "Accounts[#5].ContactMethods.Email[&1].Subtype",
"EMAIL": "Accounts[#5].ContactMethods.Email[&1].EmailAddress",
"STATUS": "Accounts[#5].ContactMethods.Email[&1].Active"
}
}
}
}
}
}
]

Related

Conditional Jolt spec for nested array

I am trying to write Jolt spec for the following input. I need to populate the primaryEmail field based on the condition if primary field is true in the emails array
[
{
"uid": "1234mark",
"name": "mark",
"userName": "markw",
"displayName": "Mark W",
"emails": [
{
"primary": false,
"value": "mark#gmail.com"
},
{
"primary": true,
"value": "mark#hotmail.com"
}
]
},
{
"uid": "9876steve",
"name": "steve",
"userName": "stevew",
"displayName": "Steve W",
"emails": [
{
"primary": false,
"value": "steve#gmail.com"
},
{
"primary": true,
"value": "steve#hotmail.com"
}
]
}
]
The desired output is
[
{
"user": {
"externalId": "1234mark",
"name": "mark",
"userName": "markw",
"displayName": "Mark W",
"primaryEmail": "mark#hotmail.com"
}
},
{
"user": {
"externalId": "9876steve",
"name": "steve",
"userName": "stevew",
"displayName": "Steve W",
"primaryEmail": "steve#hotmail.com"
}
}
]
But I get the following incorrect output since I am not able to populate the primaryEmail field conditionally properly.
[
{
"user": {
"externalId": "1234mark",
"name": "mark",
"userName": "markw",
"displayName": "Mark W"
}
},
{
"user": {
"externalId": "9876steve",
"name": "steve",
"userName": "stevew",
"displayName": "Steve W"
}
}
]
The spec I have created is the following
[
{
"operation": "shift",
"spec": {
"*": {
"uid": "[&1].user.externalId",
"name": "[&1].user.name",
"userName": "[&1].user.userName",
"displayName": "[&1].user.displayName",
"title": "[&1].user.title",
"emails": {
"*": {
"primary": {
"true": {
"#(2,value)": "primaryEmail"
}
}
}
}
}
}
}
]
Could someone please help with this query. Thanks.
What you need is to go 5 levels the three up from the innermost object while adding an extra node called user such as
[
{
"operation": "shift",
"spec": {
"*": {
"uid": "[&1].user.externalId",
"*": "[&1].user.&", // the attributes except for "uid" and "emails" array
"emails": {
"*": {
"primary": {
"true": {
"#(2,value)": "[&5].user.&2Email" // replicate literal "primary" by using &2
}
}
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

Merging two arrays by dynamically matching values using jolt

I am new to jolt and having tough time to get the desired output
Input JSON
[
{
"getPatientDemographicDetailsOutput": [
{
"Message": "SUCCESS",
"Results": [
[
{
"APS_Age__c": "7 Years",
"Id": "1234",
"LastName": "LName0915-6",
"APS_DOB__c": "2014-11-25",
"Contacts__r": {
"totalSize": 2,
"records": [
{
"Alternate_Phone_1__c": "1458296321",
"Alternate_Phone_2__c": "(732) 318-3232",
"Correspondence_City__c": "Charlotte",
"Email_Address__c": "sohel#abc.com",
"Correspondence_State__c": "NC",
"State__c": "NC",
"Patient__c": "1234",
"Correspondence_Time_Zone__c": "EST",
"Correspondence_ZipCode_Name__c": "28222",
"Primary__c": true,
"Primary_Phone__c": "Mobile",
"Correspondence_Country__c": "USA",
"Country__c": "USA",
"Address_Line_2__c": "City",
"City__c": "Charlotte",
"Type__c": "Self",
"Zip_Code_Name__c": "28222",
"Address_Line_1__c": "Bangalore",
"Id": "11111",
"Correspond_Address_Line_1__c": "Bangalore",
"Correspond_Address_Line_2__c": "City",
"Mobile_Phone_for_Campaigns__c": "+1(732) 318-1232"
},
{
"Correspondence_City__c": "INTERNAL REVENUE SERVICE",
"Correspondence_State__c": "NY",
"Type__c": "Caregiver",
"Patient__c": "1234",
"Id": "22222",
"Correspond_Address_Line_1__c": "test address",
"Correspondence_Time_Zone__c": "EST",
"Correspondence_ZipCode_Name__c": "00501",
"Primary__c": false,
"Correspondence_Country__c": "USA"
}
],
"done": true
}
}
],
[
{
"Contact__c": "11111",
"Text_Consent_Date__c": "2019-11-23",
"Text_Messaging__c": "Yes",
"Id": "54545454"
}
]
]
}
]
}
]
Expected Output
[
{
"APS_Age__c": "7 Years",
"Id": "1234",
"LastName": "LName0915-6",
"APS_DOB__c": "2014-11-25",
"Alternate_Phone_1__c": "1458296321",
"Alternate_Phone_2__c": "(732) 318-3232",
"Correspondence_City__c": "Charlotte",
"Correspond_Address_Line_1__c": "Bangalore",
"Correspond_Address_Line_2__c": "City",
"Mobile_Phone_for_Campaigns__c": "+1(732) 318-1232",
"Primary__c": true,
"Text_Consent_Date__c": "2019-11-23",
"Text_Messaging__c": "Yes"
}
]
Logic to transform last two fields Text_Consent_Date__c and Text_Messaging__c
There are two arrays in "Results" in input JSON. I want to select Text_Consent_Date__c and Text_Messaging__c from second array if Primary__c = true(select only primary contact from primary contact list) and Id (from Contacts__r) matches with Contact__c(field in second json array)
This shift operation will help you generate the required json :
[
{
"operation": "shift",
"spec": {
"*": {
"getPatientDemographicDetailsOutput": {
"*": {
"Results": {
"*": {
"*": {
"*": "[&2].&",
"Contacts__r": {
"records": {
"*": {
"Alternate_Phone_1__c": "[&1].&",
"Alternate_Phone_2__c": "[&1].&",
"Correspondence_City__c": "[&1].&",
"Correspond_Address_Line_1__c": "[&1].&",
"Correspond_Address_Line_2__c": "[&1].&",
"Mobile_Phone_for_Campaigns__c": "[&1].&",
"Primary__c": "[&1].&"
}
}
},
"Text_Consent_Date__c": "[&1].&",
"Text_Messaging__c": "[&1].&"
}
}
}
}
}
}
}
}
]

Jolt Transform - Unable to transform json array into elements are objects with the specified key/value pairs

I'm trying to transform JSON array into elements are objects with the specified key/value pairs
{
"Resource": "sorPersonRole",
"Roleid": "1",
"Timestamp": "2010-06-30 00:00:00.0",
"Release": "Public",
"DOB": "2064-09-05",
"Active": "Y",
"enterprise_id": "a12s33",
"Inactive_enterprise_id": "",
"emp_ID": "123456",
"Inactive_emp_id": "000821972",
"Username": "",
"A_ID": "fsgf1234jhgfs3",
"P_ID": "w123456",
"Is Email Valid": "Y",
"Flag": "N",
"Registered": "spring",
"Description": "mainland corp",
"End Date": null
}
Expected output:
{
"meta" : {
"Resource" : "sorPersonRole",
"Roleid" : "1",
"Timestamp" : "2010-06-30 00:00:00.0",
"Release" : "Public",
"Sorid" : "w123456"
},
"sorAttributes" : {
"DOB" : "2064-09-05",
"Active" : "Y",
"End Date" : null,
"identifiers":
[
{
"type" : "enterprise"
"enterprise_id" : "a12s33",
"Username" : ""
},
{
"type" : "former-enterprise"
"Inactive_enterprise_id" : ""
},
{
"type" : "UID"
"emp_ID" : "123456",
"Inactive_emp_id" : "000821972"
},
{
"type" : "National"
"A_ID" : "fsgf1234jhgfs3"
}
],
"mainLand:com:adhoc" : {
"Is Email Valid" : "Y",
"Flag" : "N",
"Registered" : "spring",
"Description" : "mainland corp"
}
}
}
current Jolt spec: which I am not getting desired output
[
{
"operation": "shift",
"spec": {
"Resource": "meta.&",
"P_ID": "meta.Sorid",
"Roleid": "meta.&",
"Timestamp": "meta.&",
"Release": "meta.&",
"enterprise_id": "sorAttributes.Identifiers.type.enterprise.&",
"Inactive_enterprise_id": "sorAttributes.Identifiers.type.former-enterprise.&",
"emp_ID": "sorAttributes.Identifiers.type.UID.&",
"Inactive_emp_id": "sorAttributes.Identifiers.type.UID.&",
"Username": "sorAttributes.Identifiers.type.enterprise.&",
"A_ID": "sorAttributes.Identifiers.type.National.&",
"Is Email Valid": "sorAttributes.mainLand:com:adhoc.&",
"Flag": "sorAttributes.mainLand:com:adhoc.&",
"Registered": "sorAttributes.mainLand:com:adhoc.&",
"Description": "sorAttributes.mainLand:com:adhoc.&",
"*": "sorAttributes.&"
}
}
]
I have tried the different JsonSpecs provided on different websites, could able to match expected output. Also tried using two-shift operations but no luck, Any help or suggestion will be appreciated.
Thanks.
This can help,
For the nodes to be shifted into the identifier array, shift one level more.
[
{
"operation": "shift",
"spec": {
"Resource": "meta.&",
"Roleid": "meta.&",
"Timestamp": "meta.&",
"Release": "meta.&",
"P_ID": "meta.Sorid",
"DOB": "sorAttributes.&",
"Active": "sorAttributes.&",
"End Date": "sorAttributes.&",
"Is Email Valid": "sorAttributes.mainLand:com:adhoc.&",
"Flag": "sorAttributes.mainLand:com:adhoc.&",
"Registered": "sorAttributes.mainLand:com:adhoc.&",
"Description": "sorAttributes.mainLand:com:adhoc.&",
"enterprise_id": {
"#enterprise": "sorAttributes.identifiers[#2].type",
"#": "sorAttributes.identifiers[#2].&",
"#(1,Username)": "sorAttributes.identifiers[#2].Username"
},
"Inactive_enterprise_id": {
"#former-enterprise": "sorAttributes.identifiers[#2].type",
"#": "sorAttributes.identifiers[#2].&"
},
"Inactive_emp_id": {
"#UID": "sorAttributes.identifiers[#2].type",
"#": "sorAttributes.identifiers[#2].&",
"#(1,emp_ID)": "sorAttributes.identifiers[#2].emp_ID"
},
"A_ID": {
"#National": "sorAttributes.identifiers[#2].type",
"#": "sorAttributes.identifiers[#2].&"
}
}
}, {
"operation": "modify-overwrite-beta",
"spec": {
"*": "=recursivelySquashNulls"
}
}
]

Transform JSON-JSON JOLT

I am quite new to JOLT and I need to transform my JSON files to the desired schema. This is my input
[
{
"PK": 12345,
"FULL_NAME":"Amit Prakash",
"BIRTHDATE":"1987-05-25",
"SEX":"M",
"EMAIL": "amprak#mail.com",
"PHONE": "809386731",
"TS":"2015-11-19 14:36:34.0"
},
{
"PK": 12654,
"FULL_NAME": "Rohit Dhand",
"BIRTHDATE":"1979-02-01",
"SEX":"M",
"EMAIL": "rodha#mail.com",
"PHONE": "937013861",
"TS":"2015-11-20 11:03:02.6"
},
...
]
and this is my desired output:
{
"records": [
{
"attribs": [{
"type": "customer",
"reference": "CUST"
}],
"name": "Amit Prakash",
"personal_email": "amprak#mail.com",
"mobile": "809386731",
"id": 12345
},
{
"attribs": [{
"type": "customer",
"reference": "CUST"
}],
"name": "Rohit Dhand",
"personal_email": "rodha#mail.com",
"mobile": "937013861",
"id": 12654
},
...
]
}
So far, I have only managed up to this point:
[
{
"operation": "remove",
"spec": {
"*": {
"BIRTHDATE": "",
"SEX": "",
"TS": ""
}
}
},
{
"operation": "shift",
"spec": {
"*": "records"
}
}
]
But I can't go on from here. I don't know how to rename keys in the output.
Also, what's the alternative to remove operation? remove operation is good if you have fewer keys to exclude than to include, but how about the reverse (few keys to include, more than to exclude within a JSON object)?
Spec
[
{
"operation": "shift",
"spec": {
"*": {
"PK": "records[&1].id",
"PHONE": "records[&1].mobile",
"EMAIL": "records[&1].personal_email",
"FULL_NAME": "records[&1].name"
}
}
},
{
"operation": "default",
"spec": {
"records[]": {
"*": {
"attribs[]": {
"0": {
"type": "customer",
"reference": "CUST"
}
}
}
}
}
}
]
Shift makes copy of your data, whereas the other operations do not. Thus, one way to remove stuff is to just not have it copied across in your shift spec.
Generally the remove is used to get rid of things that would "mess up" the shift.

Unable to transform a JSON Object into Array of objects using JOLT JSON library

Input JSON that I have to transform is as follows :
{
"Business": [
{
"Label": "Entertainment",
"category": "Advert",
"weight": "",
"types": [
"T1",
"T2"
]
},
{
"Label": "FMCG",
"category": "Campaign",
"weight": "",
"types": [
"T9",
"T10"
]
}
]
}
Expected Output :
{
"Business": [
{
"Label": "Entertainment",
"category": "Advert",
"weight": "",
"types": "T1"
},
{
"Label": "Entertainment",
"category": "Advert",
"weight": "",
"types": "T2"
},
{
"Label": "FMCG",
"category": "Campaign",
"weight": "",
"types": "T9"
},
{
"Label": "FMCG",
"category": "Campaign",
"weight": "",
"types": "T10"
}
]
}
I have tried the different JsonSpecs provided at the JOLT github help page. But I am not able to solve this. Any help or pointers will be appreciated.
You have to do two shift operations.
You want to "duplicate" the Label and Category based on how many entries you have in "types" array. So do that first, into a temporary "bizArray".
Also record which "type" goes with that duplicated Label and Category in a temporary "typeArray", that has the same indexes as the bizArray.
In the second shift, "join" the two parallel arrays, "bizArray" and "typesArray" to get your final array.
Spec
[
{
"operation": "shift",
"spec": {
"Business": {
"*": { // business array
"types": {
"*": { // type array
"#2": "bizArray[]", // make a copy of the whole biz object
"#": "typesArray[]"
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"bizArray": {
"*": { // bizArray index
"Label": "Business[&1].Label",
"category": "Business[&1].category",
"weight": "Business[&1].weight"
}
},
"typesArray": {
"*": "Business[&].types"
}
}
}
]