JOLT: Combine JSON array using common key - json

My JSON looks something like this, its an array of workers and an array of worksites. The workers start with a worksite id so I need to merge them with the worksites (inside an array).
[
{
"worksite_candidates": {
"worksite_id": "12345",
"worker": {
"id": "1232",
"managerId": "09"
},
"openDate": "2022-10-14",
"finalDate": "2022-12-16"
}
},
{
"worksite_candidates": {
"worksite_id": "12345",
"worker": {
"id": "1233",
"managerId": "08"
},
"openDate": "",
"finalDate": ""
}
},
{
"worksite_candidates": {
"worksite_id": "12347",
"worker": {
"id": "1234",
"managerId": "09"
},
"openDate": "2022-11-10",
"finalDate": "2022-11-12"
}
},
{
"worksite": {
"id": "12345",
"status": "2",
"dayid": "2",
"vacancys": "1",
"countryid": "2",
"arenaid": "8"
}
},
{
"worksite": {
"id": "12347",
"status": "2",
"dayid": "2",
"vacancys": "1",
"countryid": "2",
"arenaid": "8"
}
}
]
and I need to transform it using a JOLT to something like this, workers go inside the worksite as an array
[
{
"worksite": {
"id": "12345",
"status": "2",
"dayid": "2",
"vacancys": "1",
"countryid": "2",
"arenaid": "8",
"Candidates": [
{
"worker": {
"id": "1232",
"managerId": "09"
},
"openDate": "2022-10-14",
"finalDate": "2022-12-16"
},
{
"worker": {
"id": "1233",
"managerId": "08"
},
"openDate": "",
"finalDate": ""
}
]
}
},
{
"worksite": {
"id": "12347",
"status": "2",
"dayid": "2",
"vacancys": "1",
"countryid": "2",
"arenaid": "8",
"Candidates": [
{
"worker": {
"id": "1234",
"managerId": "09"
},
"openDate": "2022-11-10",
"finalDate": "2022-11-12"
}
]
}
}
]
Please suggest a JOLT to get the desired output. Can't find a way to do it

You can walk within worksite_candidates and worksite objects
while grouping the elements by worksite id values
(values of the worksite_candidates.worksite_id and worksite.id attributes) such as
[
{
"operation": "shift",
"spec": {
"*": {
"worksite_c*": {
"*": "#(1,worksite_id).worksite.Candidates[&2].&" // [&2] is for going two levels up to reach the top level indexes and grabbing them to generate array results
},
"worksite": {
"*": "#(1,id).&1.&"
}
}
}
},
{
// get rid of redundant "worksite_id" attribute
"operation": "remove",
"spec": {
"*": {
"*": {
"*": {
"*": {
"worksite_id": ""
}
}
}
}
}
},
{
// get rid of null components
"operation": "modify-overwrite-beta",
"spec": {
"*": "=recursivelySquashNulls"
}
},
{
// get rid of topmost labels of objects
"operation": "shift",
"spec": {
"*": ""
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

I think this solution is correct
[
{
//group element for id and worksite_id
"operation": "shift",
"spec": {
"*": {
"worksite": {
"id": "data.#(1,id).&",
"status": "data.#(1,id).&",
"dayid": "data.#(1,id).&",
"vacancys": "data.#(1,id).&",
"countryid": "data.#(1,id).&",
"arenaid": "data.#(1,id).&"
},
"worksite_candidates": {
"worksite_id": {
"*": {
"#2": "data.&.Candidates"
}
}
}
}
}
},
//create output with array
{
"operation": "shift",
"spec": {
"data": {
"*": "[]"
}
}
},
//remove field worksite_id
{
"operation": "remove",
"spec": {
"*": {
"Candidates": {
"*": {
"worksite_id": ""
}
}
}
}
}
]

Related

Applying cardinality for multiple columns in Jolt

I am trying to apply Jolt for below data
input:
[
{
"id": "500",
"code": "abc",
"date": "2020-10-10",
"category": 1,
"amount": 100,
"result": 0
},
{
"id": "500",
"code": "abc",
"date": "2020-10-10",
"category": 2,
"amount": 200,
"result": 1
}
]
jolt used:
[
{
"operation": "shift",
"spec": {
"*": {
"id": "#(1,id).id",
"code": "#(1,id).code",
"date": "#(1,id).group1.date",
"category": "#(1,id).group1.group2[&1].category"
}
}
},
{
"operation": "cardinality",
"spec": {
"*": {
"id": "ONE"
}
}
},
{
"operation": "shift",
"spec": {
"*": ""
}
}
]
current output:
{
"id": "500",
"code": [
"abc",
"abc"
],
"group1": {
"date": [
"2020-10-10",
"2020-10-10"
],
"group2": [
{
"category": 1
},
{
"category": 2
}
]
}
}
expected:
{
"id": "500",
"code": "abc",
"group1": {
"date": "2020-10-10",
"group2": [
{
"category": 1
},
{
"category": 2
}
]
}
}
If i keep column of code & date in cardinality, it's fine. But in my use case, there are multiple such columns to be added. Are there any better ways to handle this scenario?
You should add each added node and use "*" wildcard to represent the rest of the attributes within the cardinality transformation such as
{
"operation": "cardinality",
"spec": {
"*": {
"*": "ONE",
"group1": {
"*": "ONE",
"group2": "MANY"
}
}
}
}
where "group2": "MANY" will make group2 to be excepted for extracting only the first element of the respective list.
the demo on the site http://jolt-demo.appspot.com/ :

Jolt Conversion - iterate list within a list and form single list

I am trying to iterate lists inside a list and form a single list with multiple objects. Iterating lists, I am able to achieve. But applying tags before the list iterating to each object is not happening if there are more objects in single list.
My input request is like below:
[
{
"success": [
{
"id": "4",
"Offers": [
{
"name": "Optional",
"type": {
"id": "1",
"name": "Optional"
},
"productOfferings": [
{
"id": "3",
"name": "Test1"
}
]
},
{
"name": "Default",
"type": {
"id": "2",
"name": "Default"
},
"productOfferings": [
{
"id": "1",
"name": "Test2"
},
{
"id": "2",
"name": "Test3"
}
]
}
]
}
]
}
]
My spec is like below:
[
{
"operation": "shift",
"spec": {
"*": {
"success": {
"*": {
"Offers": {
"*": {
"name": "[&1].[&3].typeName",
"type": {
"id": "[&2].[&4].typeNameId",
"name": "[&2].[&4].typeNameValue"
},
"productOfferings": {
"*": {
"id": "[&3].[&1].id",
"name": "[&3].[&1].name"
}
}
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[]"
}
}
}
]
Output Received from spec:
[
{
"typeName": "Optional",
"typeNameId": "1",
"typeNameValue": "Optional",
"id": "3",
"name": "Test1"
},
{
"typeName": "Default",
"typeNameId": "2",
"typeNameValue": "Default",
"id": "1",
"name": "Test2"
},
{
"id": "2",
"name": "Test3"
}
]
But Expected output is like below:
[
{
"typeName": "Optional",
"typeNameId": "1",
"typeNameValue": "Optional",
"id": "3",
"name": "Test1"
},
{
"typeName": "Default",
"typeNameId": "2",
"typeNameValue": "Default",
"id": "1",
"name": "Test2"
},
{
"typeName": "Default",
"typeNameId": "2",
"typeNameValue": "Default",
"id": "2",
"name": "Test3"
}
]
If there are more objects inside productOfferings object, I am not able to add typeName,typeNameId, typeNameValue to the actual object. Please help to fix this issue.
You seem just needing to collect all into the productOfferings array while prepending each key by the common identifier [&3].[&1] such as
[
{
"operation": "shift",
"spec": {
"*": {
"success": {
"*": {
"Offers": {
"*": {
"productOfferings": {
"*": {
"#(2,name)": "[&3].[&1].typeName",
"#(2,type.id)": "[&3].[&1].typeNameId",
"#(2,type.name)": "[&3].[&1].typeNameValue",
"*": "[&3].[&1].&"
}
}
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[]"
}
}
}
]

JOLT: Copy key value and filter array

I'm trying to filter away some of the objects in the array that does not meet the condition in a given data. All the idType containing "SAL_EMP" and "MAJ_EMP" shall be removed and return only the remaining objects. But is currently not returning the "filtered" objects into its own parent.
How can modify my spec in order to achieve the desired result?
Input data:
[
{
"type": "front-desk",
"employeeIdDetails": [
{
"id": "900",
"idType": "HR_EMP"
},
{
"id": "100",
"idType": "SAL_EMP"
},
{
"id": "100",
"idType": "MAJ_EMP"
},
{
"id": "120",
"idType": "COL_EMP"
}
]
},
{
"type": "backend",
"employeeIdDetails": [
{
"id": "920",
"idType": "HR_EMP"
},
{
"id": "600",
"idType": "SAL_EMP"
},
{
"id": "160",
"idType": "COL_EMP"
},
{
"id": "400",
"idType": "MAJ_EMP"
}
]
},
{
"type": "middle-end",
"employeeIdDetails": [
{
"id": "220",
"idType": "SAL_EMP"
},
{
"id": "630",
"idType": "SAL_EMP"
},
{
"id": "460",
"idType": "SAL_EMP"
}
]
}
]
Desired data:
[
{
"type": "front-desk",
"employeeIdDetails": [
{
"id": "900",
"idType": "HR_EMP"
},
{
"id": "120",
"idType": "COL_EMP"
}
]
},
{
"type": "backend",
"employeeIdDetails": [
{
"id": "920",
"idType": "HR_EMP"
},
{
"id": "160",
"idType": "COL_EMP"
}
]
},
{
"type": "middle-end",
"employeeIdDetails": [
]
}
]
My current Jolt spec:
[
{
"operation": "shift",
"spec": {
"*": {
"type": {
"*": {
"#(2,employeeIdDetails)": {
"*": {
"idType": {
"HR_EMP": {
"#2": "[]"
},
"COL_EMP": {
"#2": "[]"
}
}
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"id": "[&1].id",
"idType": "[&1].idType"
}
}
}
]
Returning result as:
[
{
"id": "900",
"idType": "HR_EMP"
},
{
"id": "120",
"idType": "COL_EMP"
},
{
"id": "920",
"idType": "HR_EMP"
},
{
"id": "160",
"idType": "COL_EMP"
}
]
An option would be walking through employeeIdDetails array in order to apply conditional logic while combining them with the other elements which have the key type as
[
{
"operation": "shift",
"spec": {
"*": {
"type": "#(1,type).&",
"employeeIdDetails": {
"*": {
"idType": {
"SAL_EMP": {
"#2": "[]"
},
"MAJ_EMP": {
"#2": "[]"
},
"*": {
"#2": "#(5,type).&4"
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": ""
}
}
]
beneath the common keys named the values of the type elements, and then get rid of those auxiliary keys within the next level of transformation.
Manage to figure out a specs from some samples online.
[
{
"operation": "shift",
"spec": {
"*": { // item array
"*": "[&1].&",
"employeeIdDetails": {
"*": { // fixes array
"idType": {
"HR_EMP|COL_EMP": { // only match the thing you want
"#2": "[&5].employeeIdDetails[]"
}
}
}
}
}
}
}
]

JOLT get only one value from an array inside an array

I've been trying to figure out how to get the first value out of an array in my events array in this JSON.
I think I must do something with Cardinality but I can't quite figure it out so any help would be appreciated.
This is what my JSON looks like
{
"rootid": "19718",
"clloadm": "2021-06-01T22:40:02",
"clload": "2021-06-01T21:21:39",
"date": "2021-05-25T21:52:30",
"events": [
{
"done": {
"id": "e0",
"value": "2021-05-29T08:08:19"
},
"id": "e0_event",
"started": {
"id": "e0",
"value": "2021-05-29T08:08:19"
},
"status": "complete"
},
{
"done": {
"id": "e1",
"value": "2021-05-27T02:20:25"
},
"id": "e1_event",
"started": {
"id": "e1",
"value": "2021-05-27T02:20:25"
},
"status": "complete"
},
{
"done": {
"id": "e2",
"value": "2021-05-29T08:08:19"
},
"id": "e2_event",
"started": {
"id": "e2",
"value": "2021-05-29T08:08:19"
},
"status": "complete"
},
{
"done": {
"id": "e3",
"value": "2021-05-29T08:08:19"
},
"id": "e3_event",
"started": {
"id": "e3",
"value": "2021-05-29T08:08:19"
},
"status": "complete"
},
{
"done": {
"id": "e4",
"value": "2021-05-29T08:08:19"
},
"id": "e4_event",
"started": {
"id": "e4",
"value": "2021-05-29T08:08:19"
},
"status": "complete"
}
],
"ids": [
{
"id": "id",
"source": "source",
"value": "value"
}
]
}
My Jolt Spec
[
{
"operation": "shift",
"spec": {
"*": "&",
"events": {
"*": {
"*": {
"#id": {
"e0": { "#(2,value)": "&" },
"e4": { "#(2,value)": "&" }
}
}
}
},
"ids": {
"*": {
"#value": "#id"
}
}
}
}
]
The result I get:
{
"rootid" : "19718",
"clloadm" : "2021-06-01T22:40:02",
"clload" : "2021-06-01T21:21:39",
"date" : "2021-05-25T21:52:30",
"e0" : [ "2021-05-29T08:08:19", "2021-05-29T08:08:19" ],
"e4" : [ "2021-05-29T08:08:19", "2021-05-29T08:08:19" ],
"id" : "value",
"new_id" : "value"
}
I would like the result to be more like this where only the first value is selected:
{
"rootid" : "19718",
"clloadm" : "2021-06-01T22:40:02",
"clload" : "2021-06-01T21:21:39",
"date" : "2021-05-25T21:52:30",
"e0" : "2021-05-29T08:08:19",
"e4" : "2021-05-29T08:08:19",
"id" : "value",
"new_id" : "value"
}
Edit:
I've tried adding the cardinality into my spec, but I can't seem to get the result I want.
[
{
"operation": "shift",
"spec": {
"*": "&",
"events": {
"*": {
"*": {
"#id": {
"e0": { "#(2,value)": "&" },
"e4": {
"operation": "cardinality",
"spec": {
"e4": "ONE"
}
}
}
}
}
},
"ids": {
"*": {
"#value": "#id"
}
}
}
}
]
Yes, you just can add a cardinality transformation such as
{
"operation": "cardinality",
"spec": {
"*": "ONE"
}
}
or optionally use e* wildcard just to restrict the result for the arrays with keys starting with the letter e such as
{
"operation": "cardinality",
"spec": {
"e*": "ONE"
}
}
Edit : just need to add to the current spec. So, you can use the following :
[
{
"operation": "shift",
"spec": {
"*": "&",
"events": {
"*": {
"*": {
"#id": {
"e0": {
"#(2,value)": "&"
},
"e4": {
"#(2,value)": "&"
}
}
}
}
},
"ids": {
"*": {
"#value": "#id"
}
}
}
},
{
"operation": "cardinality",
"spec": {
"e*": "ONE"
}
}
]

Jolt transformation array data

I want to transform a JSON using JOLT like this:
Input: {
"array": [
"1","2","3","4"
],
"array2": [
{
"something": "123",
"something1": "Plane"
},
{
"something3": "567",
"something4": "Car"
}
]
}
Into the following format, as you can see from output I need data from both arrays to fit exact param names, not empty one like in the first or existed param names like in the second one.
Output: {
"one_array": [
{
"code": "1",
"description": "",
},
{
"code": "2",
"description": "",
},
{
"code": "3",
"description": "",
},
{
"code": "4",
"description": "",
}
], "other_array": [
{
"id": "123",
"type": "Plane"
},
{
"id": "567",
"type": "Car"
}
]
}
Some clarifications are really appreciated
You can achieve this using 2 shift operations and the default operation as below.
[
{
"operation": "shift",
"spec": {
"array": {
"*": {
"#": "one_array[&].id"
}
},
"array2": {
"*": {
"*": {
"#": "tmp_array[&2]"
}
}
}
}
},
{
"operation": "shift",
"spec": {
"one_array": "one_array",
"tmp_array": {
"*": {
"0": "other_array[&1].id",
"1": "other_array[&1].type"
}
}
}
},
{
"operation": "default",
"spec": {
"one_array[]": {
"*": {
"description": ""
}
}
}
}
]