Applying cardinality for multiple columns in Jolt - json

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/ :

Related

Jolt unnest list to top level

I have a JSON:
[
{
"id": 1015380,
"type": "campaign",
"stats": [
{
"message_sends_by_any_user": 13,
"ctr": "0.094",
}
]
},
{
"id": 1015695,
"type": "campaign",
"stats": [
{
"message_sends_by_any_user": 7,
"ctr": "0.091",
}
]
}
]
I want to "unnested" stats list to top level. JOLT config:
[
{
"operation": "shift",
"spec": {
"*": {
"id": "[&1].id",
"type": "[&1].type",
"stats": {
"*": "[&2].&"
}
}
}
}
]
Expected:
[
{
"id": 1015380,
"type": "campaign",
"message_sends_by_any_user": 13,
"ctr": "0.094",
},
{
"id": 1015695,
"type": "campaign",
"message_sends_by_any_user": 7,
"ctr": "0.091"
}
]
But actual output contains array indexes like this:
[
{
"id" : 1015380,
"type" : "campaign",
"0" : {
"message_sends_by_any_user" : 13,
"ctr" : "0.094"
}, ...
How to avoid these indexes?
You can prefer walking through the indexes of the stats list by taking id and type attributes inside such as
[
{
"operation": "shift",
"spec": {
"*": {
"stats": {
"*": {
"#(2,id)": "[&3].id",
"#(2,type)": "[&3].type",
"*": "[&3].&"
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com is

Jolt update all 0 value to 1

I would like to know in Jolt, how do I count the number of levels I need to moved up to get the required data.
I played around the Jolt spec to convert value in "quantity" from 0 to 1
Input
{
"items": [
{
"product": {
"name": "product1",
"id": "001"
},
"quantity": 1
},
{
"product": {
"name": "product2",
"id": "002"
},
"quantity": 0
},
{
"product": {
"name": "product3",
"id": "003"
},
"quantity": 0
}
]
}
The expected output
{
"items": [
{
"product": {
"name": "product1",
"id": "001"
},
"quantity": 1
},
{
"product": {
"name": "product2",
"id": "002"
},
"quantity": 1
},
{
"product": {
"name": "product3",
"id": "003"
},
"quantity": 1
}
]
}
Jolt spec with some notes for what I understand.
[
{
"operation": "shift",
"spec": {
"items": {
"*": {
"quantity": {
"0": {
"#1": "items.[&3].quantity" //[&3] => I move 3 levels up to items.* to get index?
},
"*": {
"#(2,quantity)": "items.[&3].quantity" //#(2,quantity) => I move 2 levels up to get items.*.quantity value?
}
},
"*": "items.[&1].&" //[&1] => I move 1 level up to items.* to get index?
}
}
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"items": {
"*": {
"quantity": "=toInteger(#(1,quantity))"
}
}
}
}
]
Do I understand it correctly? Please advice.
Thanks you
As much as I understand, you want to reflect the first quantity value within the items array to all other quantity values of the other objects. Then you can use these shift transformations :
[
{
"operation": "shift",
"spec": {
"items": {
"0": {
"#": "&"
},
"*": {
"#(0,product)": "&.product",
"#(2,&1[0].quantity)": "&.quantity"
}
}
}
},
{
"operation": "shift",
"spec": {
"*": "items"
}
}
]

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 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": ""
}
}
}
}
]

Flattening data from 3 nested lists, into a single list using Jolt

The actual requirement is to fetch ;parent id in each json object as described in required output. The input contains array of children in hierarchy. The respective parent id ie. if id = A_B then its parent_id shall be A.
Jolt Spec Tried:
[{
"operation": "shift",
"spec": {
"children": {
"*": {
"id2": "&",
"name": "&",
"path": "&",
"#": "[&1]",
"#(2,id)": "[&1].parent_id",
"children": {
"*": {
"#": "[&1]",
"#(3,id2)": "[&1].parent_id2"
}
}
}
}
}
}]
#
INPUT
#
{
"categories": [
{
"id": "A",
"name": "firstName",
"path": "firstPath",
"children": [
{
"id": "A_B",
"name": "secondName",
"path": "secondPath",
"children": [
{
"id": "A_B_C",
"name": "thirdName",
"path": "thirdPath"
}
]
}
]
}
]
}
#
Required this OUTPUT
#
[{
"id": "A",
"name": "firstName",
"path": "firstPath",
"parentId": "0"
},
{
"id": "A_B",
"name": "secondName",
"path": "secondPath",
"parentId": "A"
},
{
"id": "A_B_C",
"name": "thirdName",
"path": "thirdPath",
"parentId": "A_B"
}]
Spec : Run each step individually to see what it is doing.
[
{
// bootstrap the root level to have "parentId": "0"
"operation": "default",
"spec": {
"categories[]": {
"0": {
"parentId": "0"
}
}
}
},
{
// Build the "data" object you want, but you have to do it
// maintaining the 3 levels of nested lists as the input
// so that the lookups will work.
"operation": "shift",
"spec": {
"categories": {
"*": {
"*": "root[&1].data.&",
"children": {
"*": {
"*": "root[&3].firstLevel[&1].data.&",
"#(2,id)": "root[&3].firstLevel[&1].data.parent_id",
"children": {
"*": {
"*": "root[&5].firstLevel[&3].secondLevel[&1].data.&",
"#(2,id)": "root[&5].firstLevel[&3].secondLevel[&1].data.parent_id"
}
}
}
}
}
}
}
},
{
// Lastly, accumulate all the finished "data" elements from the
// 3 nested arrays into a single top level array.
"operation": "shift",
"spec": {
"root": {
"*": {
"data": "[]",
"firstLevel": {
"*": {
"data": "[]",
"secondLevel": {
"*": {
"data": "[]"
}
}
}
}
}
}
}
}]