Implicit array creating in jolt - jolt

Input:
{
"categories": {
"1": {
"name": "Books"
},
"2": {
"name": "Games"
}
}
}
Spec:
[
{
"operation": "shift",
"spec": {
"categories": {
"*": {
"#": "categories"
}
}
}
}
]
Output (array of categories):
{
"categories" : [ {
"name" : "Books"
}, {
"name" : "Games"
} ]
}
Another Input with just one element
{
"categories": {
"1": {
"name": "Books"
}
}
}
Output:
{
"categories" : {
"name" : "Books"
}
}
I expected the output to be a categories array containing just one element. Why does this spec not create an array when there is a single element?

I managed this problem with following transformation:
[
{
"operation": "shift",
"spec": {
"*": {
"*": "categories[#1]"
}
}
}
]

Related

Facing issue with JOLT transformation with nested array

I have a JSON input :
{
"id": "Root_ID",
"Item": [
{
"id": "ID_1",
"characteristic": [
{
"name": "char1",
"value": "PRE1"
},
{
"name": "char2",
"value": "2050-01-01"
}
]
},
{
"id": "ID_2",
"characteristic": [
{
"name": "char1",
"value": "PRE2"
},
{
"name": "char2",
"value": "2050-01-02"
}
]
}
]
}
which needs to be converted by using a Jolt transformation spec to the following output :
{
"id": "Root_ID",
"Item": [
{
"id": "ID_1",
"char1": "PRE1",
"char2": "2050-01-01"
},
{
"id": "ID_2",
"char1": "PRE2",
"char2": "2050-01-02"
}
]
}
Currently, I'm using this spec :
[
{
"operation": "shift",
"spec": {
"id": "id",
"Item": {
"*": {
"characteristic": {
"*": {
"name": {
"char1": {
"#(2,value)": "item[#3].char1"
},
"char2": {
"#(2,value)": "item[#3].char2"
}
}
}
}
}
}
}
}
]
which does not produce the desired result.
Can you please help me prepare a correct spec to handle this issue ?
Edit : What if I'd like to get the following JSON result ?
{
"id": "Root_ID",
"Item": [
{
"id": "ID_1",
"char1": "PRE1"
},
{
"id": "ID_2",
"char1": "PRE2",
"char2": "2050-01-02"
}
]
}
You can use the following shift transformation spec in which #value and #name are matched reciprocally such as
[
{
"operation": "shift",
"spec": {
"id": "&",
"Item": {
"*": {
"id": "&2[&1].&",// you can reduce two levels based on the inner identifier 4,3 -> 2,1
"char*": {
"*": {
"#value": "&4[&3].#name" // &4 copies the literal "Item" after going four levels up the tree, [&3] generates array-wise result(array of objects) after going three levels up the tree to reach the level of the indexes of the "Item" array
}
}
}
}
}
}
]
Edit : You can alternatively use the following spec for the case in which you need to return char2 within the all objects but the first :
[
{
"operation": "shift",
"spec": {
"id": "&",
"Item": {
"0": {// stands for the first index
"id": "&2[&1].&",
"char*": {
"*": {
"name": {
"char1": {
"#2,value": "&6[&5].#3,name"
}
}
}
}
},
"*": {
"id": "&2[&1].&",
"char*": {
"*": {
"#value": "&4[&3].#name"
}
}
}
}
}
}
]

Having issue when adding a common value to every elements in array using Jolt

I am currently using Jolt to work on this input:
{
"banking_account": {
"accounts": [
{
"accountId": "account1"
},
{
"accountId": "account2",
"nickname": "nickname2"
}
]
},
"account_balance": {
"total_value": {
"currency_code": "USD",
"value": "100.00"
},
"balance_accounts": [
{
"id": "id1"
},
{
"id": "id2"
}
]
}
}
And the expected output is:
{
"Data": {
"Accounts": [
{
"AccountId": "account1",
"Account": {
"Identification": [
"id1",
"id2"
]
},
"Currency": "USD"
},
{
"AccountId": "account2",
"NickName": "nickname2",
"Account": {
"Identification": [
"id1",
"id2"
]
},
"Currency": "USD"
}
]
}
}
And here is my current spec:
[
{
"operation": "shift",
"spec": {
"banking_account": {
"accounts": {
"*": {
"accountId": "Data.Accounts.[&1].AccountId",
"nickname": "Data.Accounts.[&1].NickName"
}
}
},
"account_balance": {
"total_value": {
"currency_code": "Data.Accounts.[&1].Currency"
},
"balance_accounts": {
"*": {
"id": "Data.Accounts.[&1].Account.Identification"
}
}
}
}
}
]
And here is my current output:
{
"Data": {
"Accounts": [
{
"AccountId": "account1",
"Account": {
"Identification": "id1"
}
},
{
"AccountId": "account2",
"NickName": "nickname2",
"Account": {
"Identification": "id2"
}
}
]
}
}
So I am having two questions:
Why is the "Currency" value missing? Even if I added something like
"account_balance": {
"total_value": {
"currency_code": "Data.Accounts.[&1].Currency"
}
}
How to map both two balances accounts to both two accounts? Now it seems like an 1->1 mapping; and I wish to have a 2*2 mapping.
Thanks a lot for your help in advance!
You can use this spec for your solution but point 2 is not covered in this and I have added reason for 2nd:
[
{
"operation": "shift",
"spec": {
"banking_account": {
"accounts": {
"*": {
"accountId": "Data.Accounts.[&1].AccountId",
"nickname": "Data.Accounts.[&1].NickName"
}
}
},
"account_balance": {
"total_value": {
"currency_code": "Data.Currency"
},
"balance_accounts": {
"*": {
"id": "Data.Identification"
}
}
}
}
}, {
"operation": "shift",
"spec": {
"Data": {
"Accounts": {
"*": {
"*": "Data.Accounts.[&1].&",
"#(2,Currency)": {
"USD": {
"#USD": "Data.Accounts.[&2].Currency"
}
}
}
},
"Identification": "Data.Identification"
}
}
}
]
& This will answer your two questions :
1 : Why is the "Currency" value missing? Even if I added something like
So you are basically populating a single field element as multiple fields in an array with [&1] which is not possible that's why its not populating.
To do such a case you need to create new elements that will be populating in the Accounts array if you see my spec I am adding a new Current field in every object of Accounts array ->
"Accounts": {
"*": {
"*": "Data.Accounts.[&1].&",
"#(2,Currency)": { //Going 2 levels up to get to currency
"USD": { //If else to check Currency is USD
"#USD": "Data.Accounts.[&2].Currency" //Adding the field in each object of Accounts array.
}
}
}
How to map both two balances accounts to both two accounts? Now it seems like an 1->1 mapping; and I wish to have a 2*2 mapping.
--> This can be achieved in the similar way I have done for 1 but this will again require alot of hardcoding in JOlt.
So my suggestion is to keep both Currency and Identification outside Accounts Array in Data as single object.

Jolt giving values as root

Here's my input data :
[
{
"TEST1": "abcd",
"TEST2": "xyz",
"TEST3": "08"
},
{
"TEST1": "abcd",
"TEST2": "xyz",
"TEST3": "20"
}
]
Output
[
{
"TEST1": "root",
"TEST2": "xyz",
"TEST3": ["08","20"]
}
]
Expected Output
[
{
"TEST1": "abcd",
"TEST2": "xyz",
"TEST3": ["08","20"]
}
]
Jolt specs
[
{
"operation": "shift",
"spec": {
"": {
"TEST3": "#(1,TEST2).TEST3"
}
}
},
{
"operation": "shift",
"spec": {
"": {
"$1": "[#2].TEST1",
"$": "[#2].TEST2",
"#.TEST3": "[#2].TEST3"
}
}
}
]
Can you please help me in achieving the excpected output
Check this spec
[
//Concat the TEST1 and TEST2 to temp
{
"operation": "modify-default-beta",
"spec": {
"*": {
"temp": "=concat(#(1,TEST1),':',#(1,TEST2))"
}
}
},
//Group the values by shifting TEST3
{
"operation": "shift",
"spec": {
"*": {
"TEST3": "#(1,temp)"
}
}
},
// Assign the keys to the node named key and value to the node nameed value
{
"operation": "shift",
"spec": {
"*": {
"#": "[#2].key",
"$": "[#2].value"
}
}
},
//Shift and assign the respective values to the TEST1, TEST2 and TEST3
{
"operation": "shift",
"spec": {
"*": {
"value": {
"*:*": {
"$(0,1)": "[&3].TEST1",
"$(0,2)": "[&3].TEST2"
}
},
"key": "[&1].TEST3"
}
}
}
]

Compare and Combine Objects of same array

I want to iterate each object and map system.myStringValue with value.myStringValue
Can you provide spec for the same ?
I have provided the following input and output json. If any other things require form my side , let me know. I have tried with another spec but its not working for me as I want to combine email and phone in one object
Input :
[
{
"telecom": [
{
"system": {
"myStringValue": "email"
},
"value": {
"myStringValue": "mobqa#tester.com"
}
},
{
"system": {
"myStringValue": "phone"
},
"value": {
"myStringValue": "123"
}
}
]
},
{
"telecom": [
{
"system": {
"myStringValue": "email"
},
"value": {
"myStringValue": "john.doe#tester.com"
}
}
]
},
{
"telecom": [
{
"system": {
"myStringValue": "email"
},
"value": {
"myStringValue": "Gayle55#tester.com"
}
}
]
}
]
Output:
{
"users": [
{
"email":"mobqa#tester.com",
"phone":"123"
},
{
"email":"john.doe#tester.com"
},
{
"email":"Gayle55#tester.com"
}
]
}
[
{
"operation": "shift",
"spec": {
"*": {
"telecom": {
"*": {
"value": {
"myStringValue": {
// # takes value of 'value.myStringValue' and puts it into 'users[&5]' occurence
// #(3,system.myStringValue) go up four levels and then go to 'system.myStringValue'
// value and grab it and put as key value to appropriate occurence of 'users'
"#": "users[&5].#(3,system.myStringValue)"
}
}
}
}
}
}
}
]

Jolt - recurcive process

I try to flatten some JSON arrays using Jolt. I found how to do it on the first level, but I need to do it "recursively".
About the input:
the array I want to flatten are name "objects"
the inner objects all contain a "name" attribute but the others attributes are not common
Here is a simple sample:
{
"objects": [
{
"name": "first",
"type": "FIRST",
"1st_attr": 0
},
{
"name": "second",
"type": "SECOND",
"2nd_attr": 0
}
],
"sub": {
"objects": [
{
"name": "third",
"type": "THIRD",
"3rd_attr": 0
}
]
}
}
Here is the output I want:
{
"first" : {
"1st_attr" : 0,
"name" : "first",
"type" : "FIRST"
},
"second" : {
"2nd_attr" : 0,
"name" : "second",
"type" : "SECOND"
},
"sub" : {
"third" : {
"3rd_attr" : 0,
"name" : "third",
"type" : "THIRD"
}
}
}
The spec I have flatten the first level, but I would like to have it flatten every level (meanining, not just the second ;)...):
[
{
"operation": "shift",
"spec": {
"objects": {
"*": {
"#": "#(1,name)"
}
},
"*": "&0"
}
}
]
Thanks for your help
With Jolt you have to know where in your input the "object" arrays are. There isn't a way to "just find and flatten all the arrays, no matter where they are in the input doc".
Spec for the input and output you provided :
[
{
"operation": "shift",
"spec": {
"objects": {
"*": "#(0,name)"
},
"sub": {
"objects": {
"*": "&2.#(0,name)"
}
}
}
}
]
Edit: added &2. to have sub.third instead of just third