Conditional replacement of values in JOLT - json

I try to replace a value conditionally in JOLT. The first step is to check whether the key "links" exists. If this key exists, it should also be checked whether the key "type" has the value "null". If both conditions are true, the value of the key "type" shall be changed to "buttons".
In the example, this condition only applies to flow1.
Sample Input:
{
"flows": {
"flow1": { // <--- Only this object fulfills both conditions ("link" exist, "type" = null)
"link": "linkname",
"type": "null" // <--- This value is to be replaced
},
"flow2": {
"link": "linkname",
"type": "text"
},
"flow3": {
"type": "null"
}
}
}
Expected Output:
{
"flows": {
"flow1": {
"link": "linkname",
"type": "button" // <-- replaced value
},
"flow2": {
"link": "linkname",
"type": "text"
},
"flow3": {
"type": "null"
}
}
}
My Spec:
[
{
"operation": "shift",
"spec": {
"flows": {
"*": {
"link": {
"#(1,type)": {
"null": {
"#button": "&5.&4.type"
}
},
"*": "&3.&2.&"
},
"*": "&2.&1.&"
}
}
}
}
]

You're on the right track. Just apply some little tweaks within the current shift transformation, and then apply cardinality transformation in order to pick the first components of the generated arrays for the type attribute such as
[
{
"operation": "shift",
"spec": {
"flows": {
"*": {
"link": {
"#(1,type)": {
"null": {
"#button": "&5.&4.type"
},
"*": {
"#(3,type)": "&5.&4.type"
}
},
"#": "&3.&2.&"
},
"*": "&2.&1.&"
}
}
}
},
{
"operation": "cardinality",
"spec": {
"*": {
"*": {
"type": "ONE"
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

Related

Pull elements out of two arrays to make a "flat" item list

I need to merge array data from two different arrays from the Input JSON and make a flat list of items in the Output JSON. The first array contains the key required for the output and the second array contains the value.
So far, all my attempts at a spec haven't even come close, which is why I haven't listed one. Please see the Input and Desired Output below. Thanks for any help!!
Input JSON :
{
"data": [
{
"2": {
"value": "DC1"
},
"3": {
"value": 5
}
},
{
"2": {
"value": "DC2"
},
"3": {
"value": 10
}
}
],
"fields": [
{
"id": 2,
"label": "DataCenter",
"type": "text"
},
{
"id": 3,
"label": "CCount",
"type": "numeric"
}
],
"metadata": {
"numFields": 2,
"numRecords": 2,
"skip": 0,
"totalRecords": 2
}
}
Desired Output JSON:
[
{
"DataCenter": "DC1",
"CCount": "5"
},
{
"DataCenter": "DC2",
"CCount": "10"
}
]
You can use this spec:
[
{
"operation": "shift",
"spec": {
"data": "&",
"fields": {
"*": {
"label": "fields.#(1,id)"
}
}
}
},
{
"operation": "shift",
"spec": {
"data": {
"*": {
"*": {
"*": "[&2].#(4,fields.&1)"
}
}
}
}
}
]
In your desired output CCount value is a string, You can add the below spec to change an integer to a string.
,
{
"operation": "modify-overwrite-beta",
"spec": {
"*": {
"CCount": "=toString"
}
}
}
You might reciprocally match id value of fields array vs. the object keys of the data array within a common object within the first shift transformation spec in order to prepare for the second one in which we tile the attributes into their individual objects such as
[
{
"operation": "shift",
"spec": {
"*": { // represents the node for both "data" and "fields" arrays
"*": {
"*": {
"value": "&1.&",
"#1,label": "#2,id.&"
}
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"value": {
"*": "[&].#2,label"
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

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

JOLT Specification to Transform field value to field name

I am trying to convert below json payload into a json payload which has field name as the value of the field:
Can you please help to provide jold specification for this ?
Input JSON Payload :
{
"action": {
"allowPartialSuccess": false,
"records": [
{
"recordid": "a4c6364e-4446-47d0-b014-c20ca014fdb3",
"ShipToCustomerTextualAddress__c": "TestAddress1",
"ResellerPO__c": "TestAddress1",
"InvoiceCDBID__c": "TestAddress1"
},
{
"recordid": "73781a94-9660-4f69-9bde-f2bf1991317d",
"ShipToCustomerTextualAddress__c": "TestAddress2",
"ResellerPO__c": "TestAddress2",
"InvoiceCDBID__c": "TestAddress2"
}
],
"type": "update"
}
}
Desired Output Payload :
{
"action": {
"allowPartialSuccess": false,
"records": {
"a4c6364e-4446-47d0-b014-c20ca014fdb3": {
"ShipToCustomerTextualAddress__c": "TestAddress1",
"ResellerPO__c": "TestAddress1",
"InvoiceCDBID__c": "TestAddress1"
},
"73781a94-9660-4f69-9bde-f2bf1991317d": {
"ShipToCustomerTextualAddress__c": "TestAddress2",
"ResellerPO__c": "TestAddress2",
"InvoiceCDBID__c": "TestAddress2"
}
},
"type": "update"
}
}
This will help you resolve it.
#(level,attribute) -->does the work.
[
{
"operation": "shift",
"spec": {
"action": {
"*": "action.&",
"records": {
"*": {
"ShipToCustomerTextualAddress__c": "action.records.#(1,recordid).&",
"ResellerPO__c": "action.records.#(1,recordid).&",
"InvoiceCDBID__c": "action.records.#(1,recordid).&"
}
}
}
}
}
]
You can think symbolically through use of ampersands to replicate the respective values within a shift transformation, and a remove transformation in order to get rid of the undesired attribute(recordid) at the end such as
[
{
"operation": "shift",
"spec": {
"*": {
"records": {
"*": "&2.&1.#(0,recordid)" // &2(going two levels up) stands for replicating "action", &1 is for "records"
},
"*": "&1.&" // which represents the "else" case(eg. all but the "records" object); &1 is for "action", and & is for "records"
}
}
},
{
"operation": "remove",
"spec": {
"*": {
"*": {
"*": {
"recordid": ""
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is
You would use this for solution this problem.
[
{
"operation": "shift",
"spec": {
"action": {
"*": "action.&",
"records": {
"*": "action.records.#recordid"
}
}
}
}
]

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