JSON Jolt If Else - json

could someone help me with this?
If 01 is given in "decision", we display from field A under the name "First", and if it is 02, we display from field A under the name "Second".
In both cases, we add "xyz" to the value in field A at the end.
Input:
{
"Some": {
"Numbers": {
"Number": [
{
"Int": {
"A": "45618975618"
}
}
]
},
"Z": {
"X": [
{
"decision": {
"value": [
"01"
]
}
}
]
}
}
}
Expected output for a 01:
{
"A" : {
"B" : {
"First" : {
"A" : "45618975618XYZ"
}
}
}
}

You can use the following spec
[
{//conditionally match the respective values
"operation": "shift",
"spec": {
"#(0,Some.Z.X[0].decision.value[0])": { // comparison criteria
"01": {
"#(2,Some.Numbers.Number[0].Int.A)": "A.B.First.A"
},
"02": {
"#(2,Some.Numbers.Number[0].Int.A)": "A.B.Second.A"
}
}
}
},
{
//add literal "XYZ" to the end of the returned value
"operation": "modify-overwrite-beta",
"spec": {
"*": {
"*": {
"*": {
"*": "=concat(#(1,&),'XYZ')"
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

Related

Combine shifted values and default values into a same sub object using Jolt

Input:
{
"banking_account": {
"accounts": [
{
"accountId": "id1"
},
{
"accountId": "id2"
}
]
}
}
Expected output:
{
"Data": {
"Accounts": [
{
"Account": {
"Attribute1": "default",
"Identification": "id1"
}
},
{
"Account": {
"Attribute1": "default",
"Identification": "id2"
}
}
]
}
}
My current spec:
[
{
"operation": "shift",
"spec": {
"banking_account": {
"accounts": {
"*": {
"accountId": "Data.Accounts.[&1].Account.Identification"
}
}
}
}
},
{
"operation": "default",
"spec": {
"Attribute": "default"
}
},
{
"operation": "shift",
"spec": {
"Data": {
"Accounts": {
"*": {
"*": "Data.Accounts.[&1].&",
"#(3,Attribute)": "Data.Accounts.[&1].Account.Attribute1"
}
}
}
}
}
]
Current output:
{
"Data": {
"Accounts": [
{
"Account": [
{
"Attribute1": "default"
},
{
"Identification": "id1"
}
]
},
{
"Account": [
{
"Attribute1": "default"
},
{
"Identification": "id2"
}
]
}
]
}
}
It seems instead of inserting the key-value pair into the existing "Account" sub-object, it's making "Account" as a list, with one sub-object containing "Identification", and another object containing "Attribute1".
Could you help me understand why this happens, and how could I configure to avoid this?
Thanks a lot for your help in advance!
Just prefixing the desired fixed value(default) with a # symbol would handle along with using a single shift transformation spec as in the following
[
{
"operation": "shift",
"spec": {
"banking_account": {
"a*s": {
"*": {
"#default": "Data.A&(2,1)s[&1].A&(2,1).Attribute1", // "&(2,1)" represents going tree two levels up and grabbing the second piece(with index 1 which's after 0) from the literal(`accounts`) splitted by asterisk symbols
"accountId": "Data.A&(2,1)s[&1].A&(2,1).Identification"
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

conditional JSON transformation in JOLT

I need to process response from SOLR service that looks like following:
{
"data": {
"distanceUnits": "mi", //it can be "mi", "MI", "miles", "km", "KM", etc.
"solrResponse": {
"header": {
"found": 32,
"retrieved": 10,
... //there can be other things like timestamp
},
"results": [
{
"matchScore": "08768",
"indicators" [{...}],
"location": {
... //there are about hundred attributes
"distance": "2.7649" //distance always in km
"similarity": "0.342"
},
...
]
}
The transformation need to return everything from solrResponse practically intact except two things:
similarity need to be renamed to similarityScore and moved up next to matchScore.
If distanceUnit is specified as miles, distance need to be converted to miles (i.e. divided by 1.609)
distance value is to berounded to 2 digits after decimal point and concatenated with distanceUnit.
I have created the following spec:
[
{
"operation": "modify-overwrite-beta",
"spec": {
"data": {
"unit1": "=toLower(#(1,distanceUnit))",
"unit2": "=substring(#(1,unit1),0,1)",
"solrResponse": {
"results": {
"": {
"dist1": "=divideAndRound(2,#(1,distance),0.6215)",
"distanceMiles": "=concat(#(1,dist1), ' ', #(2,distanceUnit))",
"dist2": "=divideAndRound(2,#(1,distance),1.0)",
"distanceKm": "=concat(#(1,dist2), ' ', #(2,distanceUnit))"
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"data": {
"solrResponse": {
"header": "&1",
"response": {
"": {
"&1.similarity": "similarityScore",
"unit2": {
"m": {
"distanceMiles": "locations.distance"
},
"": {
"distanceKm": "locations.distance"
}
},
"": "&1"
}
}
}
}
}
}
]
Unfortunately it does not work. Please help me.
The Jolt doesn't have a function such as multiply or product, but divide and divideAndRound to be used in a modify transformation spec. Then, we'll have a conditional to filer out whether the provided value for distanceUnit attribute exists within the list(mi,m,Mi,MI) or not such as
[
{
"operation": "modify-overwrite-beta",
"spec": {
"*": { // this outer one represents "locations" list(if there's no other outer level list or object, otherwise replace "*" with the key name "locations")
"*": { // this one stands for "locations" list's indexes
"distanceinMiles_": "=divideAndRound(2,#(1,distance),0.6215040397762585)",
"distanceinMiles": "=concat(#(1,distanceinMiles_),' ',#(1,distanceUnit))",
"distance_": "=divideAndRound(2,#(1,distance),1)",
"distance": "=concat(#(1,distance_),' ',#(1,distanceUnit))"
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": {
"address": "&2[&1].&",
"city": "&2[&1].&",
"state": "&2[&1].&",
"postalCode": "&2[&1].&",
"distanceUnit": {
"mi|m|Mi|MI": { "#(2,distanceinMiles)": "&4[&3].distance" },
"*": { "#(2,distance)": "&4[&3].distance" }
}
}
}
}
}
]
where
#(1,distanceXx) in the first spec represents traversing one colon(:) (as a Right-Hand-Side element) in order to reach the
original level of the elements #(1,distanceXx), while
#(2,distanceXx) stands for traversing { (object opening "curly" brace) twice to reach the same.
the attributes at the indexes level of "locations" are combined by using [&1] and [&3] respectively
&2 and &4 are substituted respectively to denote the key name
"locations"
the demo on the site http://jolt-demo.appspot.com/ :
Edit (response for your last edit):
Considering the input
{
"data": {
"distanceUnit": "Mi",
"solrResponse": {
"header": {
"found": 32,
"retrieved": 10
},
"results": [
{
"matchScore": "08768",
"location": {
"distance": "2.7649",
"similarity": "0.342"
}
}
]
}
}
}
you can use the following specs
[
{
"operation": "modify-overwrite-beta",
"spec": {
"data": {
"distanceUnit": "=toLower(#(1,&))",
"solrResponse": {
"results": {
"*": {
"location": {
"dist1": "=divideAndRound(2,#(1,distance),0.6215)",
"distanceKm": "=concat(#(1,dist1), ' km')",
"dist2": "=divideAndRound(2,#(1,distance),1.0)",
"distanceMiles": "=concat(#(1,dist2), ' km')"
}
}
}
}
}
}
},
{
"operation": "shift",
"spec": {
"data": {
"*": "&1.&",
"solrResponse": {
"*": "&2.&1.&",
"results": {
"*": {
"*": "&4.&3.&2[&1].&",
"location": {
"#(4,distanceUnit)": {
"mi": { "#(2,distanceKm)": "&7.&6.&5[&4].&3.distance" },
"km": { "#(2,distanceMiles)": "&7.&6.&5[&4].distance" }
},
"similarity": "&5.&4.&3[&2].&Score"
}
}
}
}
}
}
},
{
"operation": "sort"
}
]
the demo is :

Validating and transform the array objects in JOLT

Would like to have the output JSON based on the active status in the input array.If active is true provide the value object.
INPUT :
{
"services": [
{
"active": true,
"value": "Clampable",
"key": "40300"
},
{
"active": false,
"value": "Mixed load",
"key": "40302"
}
]
}
SPECS:
[
{
"operation": "shift",
"spec": {
"services": {
"*": {
"key": {
"40302": {
"#mixed": "loading_method"
},
"40300": {
"#clampable": "loading_method"
}
}
}
}
}
}
]
OUTPUT :
"loading_method" : [ "clampable", "mixed"]
I do not want the mixed value as output as the status is false.
Any advise would be great..
This works,
If active is true then, shift the value node.
[
{
"operation": "shift",
"spec": {
"services": {
"*": {
"active": {
"true": {
"#(2,value)": "loading_method"
}
}
}
}
}
}
]

JOLT spec array of objects remove key

I'm trying to understand how to remove the key and object layers for the below. Any help would be greatly appreciated. Trying to use a JOLT processor in NIFI to address this data change.
INPUT:
[ {
"rbr" : {
"fetchTime" : "2020-07-06T23:46:23.677Z",
"customMetadata" : {
"x" : "1",
"o2" : {
"x2" : "y"
}
}
},
"xyz": {
"fetchTime" : "2020-07-06T23:46:23.677Z",
"customMetadata" : {
"x" : "1",
"o2" : {
"x2" : "y"
}
}
}
}
]
desired output:
[
{
"fetchTime" : "2020-07-06T23:46:23.677Z",
"customMetadata" : {
"x" : "1",
"o2" : {
"x2" : "y"
}
},
"type": "rbr"
},
{
"fetchTime" : "2020-07-06T23:46:23.677Z",
"customMetadata" : {
"x" : "1",
"o2" : {
"x2" : "y"
}
},
"type": "xyz"
}
]
Can be done with simple shift operation
[
{
"operation": "shift",
"spec": {
"*": {
"*": {
"fetchTime": "[#2].fetchTime",
"customMetadata": "[#2].customMetadata",
"$": "[#2].type"
}
}
}
}
]
Edit 1
Can shift all the values from current level using "#": "[#3].&",
[
{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": {
"#": "[#3].&",
"$1": "[#3].type"
}
}
}
}
},
{
"operation": "modify-overwrite-beta",
"spec": {
"*": {
"type": "=firstElement(#(1,type))"
}
}
}
]
Iterate over the array, and for each obj create newObj like so:
objKey=Object.keys(obj)[0];
newObj=obj[objKey];
newObj.type=objKey;
and push into new array.

Find element by id in json

need to transform based on the element value
input.json
{
"Result": {
"owner": {
"name": "test user"
},
"Components": [
{
"id": "123-456-789"
}
],
"123-456-789": {
"temp": {
"emip": "abc",
"teto": "123"
}
}
}
}
transform json
[
{
"operation": "shift",
"spec": {
"Result": {
"Components": {
"*": {
"id": "compId"
}
},
"compId": {
"#": "component"
}
}
}
},
{
"operation": "default",
"spec": {
"compId": null
}
}
]
output expected to be
"123-456-789": {
"temp": {
"emip": "abc",
"teto": "123"
}
}
but the result answer is below , when I hard code the value with 123-456-789 then I get the value but I need to take the value dynamically.
{
"compId" : "123-456-789"
}
Spec
[
{
"operation": "shift",
"spec": {
"Result": {
"Components": {
"*": { // components array index
"id": {
"*": { // match any value of id
// go back up the tree 5 levels, and then
// lookup a key based on the value of the "id"
// and write that to the output at at that same
// key
"#(4,&)": "&1"
}
}
}
}
}
}
}
]