Chose the right fields depend on another field value - java

I wanted to know if there is way using jolt to select only fields that contain the value of another ?
Here is my input
{
"type": "A",
"field1": "value1",
"field2": "value2",
"example1-A1[zone=fr,method=A]": "80",
"example2-A1[zone=fr,method=A]": "90",
"example1-B1[zone=fr,method=B]": "50",
"example2-B1[zone=fr,method=B]": "10"
}
My output will depend on the value in the "type" field and check the method if it is equal to that type(eg: A) in order to select the values and will be like
{
"type": "A",
"field1": "value1",
"field2": "value2",
"new-filed1": "80",
"new-field2": "90"
}
Any help would be appreciate

Answer for the updated question:
[
{
"operation": "shift",
"spec": {
"*-*,method=*]": "fieldsByMethod.&(0,3).&(0,1)",
"type": [
"&",
"otherFields.&"
],
"*": "otherFields.&"
}
},
{
"operation": "shift",
"spec": {
"type": {
"*": {
"#(2,fieldsByMethod.&)": "&1"
}
},
"otherFields": "otherFields"
}
},
{
"operation": "shift",
"spec": {
"*": {
"example*": "new-field&(0,1)",
"*": "&"
}
}
}
]
Comparing the old and the updated input we have three additional requirements:
Fields without the ,method= substring should also be in the output.
For that we can temporarily place them in otherFields subdocument.
The type field should also be in the output:
That's why
"type": [
"&",
"otherFields.&"
]
comes in handy. & rewrites the type field to it's original place, so we can use it as in the old answer. otherFields.& puts it also to the otherFields subdocument.
Rename the example* fields to new-field*. That happens in the last operation
Old answer for the spec:
{
"type": "A",
"example1-A1[zone=fr,method=A]": "80",
"example2-A1[zone=fr,method=A]": "90",
"example1-B1[zone=fr,method=B]": "50",
"example2-B1[zone=fr,method=B]": "10"
}
and the expected output:
{
"example1": "80",
"example2": "90"
}
This spec produces the expected output for the example:
[
{
"operation": "shift",
"spec": {
"type": "type",
"*-*,method=*]": "fieldsByMethod.&(0,3).&(0,1)"
}
},
{
"operation": "shift",
"spec": {
"type": {
"*": {
"#(2,fieldsByMethod.&)": "&1"
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "&"
}
}
}
]
To understand it, try to apply it step by step.
For the second (I think the trickiest one) operation I found the issue https://github.com/bazaarvoice/jolt/issues/480 that helped me to create it.
To understand the first operation, try to analyze the https://jolt-demo.appspot.com/#prefixSoupToBuckets example.

Related

Jolt transform array into multiple Objects

I am trying to transform the below JSON:
Input:
{
"steps": [
{
"end": "2023-01-27T09:19:29.849298Z",
"id": "1",
"start": "2023-01-27T09:18:24.59325Z",
"name": "foo"
},
{
"end": "2023-01-28T09:19:29.849298Z",
"id": "2",
"start": "2023-01-28T09:18:24.59325Z",
"name": "bar"
}
]
}
Output:
{
"steps": [
{
"end": "2023-01-27T09:19:29.849298Z",
"id": "1",
"name": "foo",
"start": "2023-01-27T09:18:24.59325Z"
},
{
"end": "2023-01-28T09:19:29.849298Z",
"id": "2",
"name": "bar",
"start": "2023-01-28T09:18:24.59325Z"
}
],
"date": [
{
"name": "startDate",
"value": "2023-01-27T09:18:24.59325Z" //steps[0].start
},
{
"name": "endDate",
"value": "2023-01-27T09:19:29.849298Z" //steps[0].end
}
]
}
I tried using the below spec:
[
{
"operation": "shift",
"spec": {
"steps": {
"*": "steps[]",
"0": {
"#startDate": "date[0].name",
"start": "date[0].value",
"end": "date[1].value",
"#endDate": "date[1].name"
}
}
}
}
]
But "*": "steps[]" only transforms the last element of the array steps. Please guide me as to what is wrong with the above spec, as I am new to jolt. Also, any pointers to the correct operations needed to achieve the above output will be greatly appreciated.
You can use this spec:
[
{
"operation": "shift",
"spec": {
"*": {
"#": "&1",
"0": {
"#startDate": "date[0].name",
"start": "date[0].value",
"#endDate": "date[1].name",
"end": "date[1].value"
}
}
}
}
]
You can use # to get the steps array and put it into the steps key with &1.
The issue with the given Jolt spec is that the transformation of the steps array elements is only happening for the last element of the array. This is because the "*": "steps[]" directive only applies to the last element of the array.
To transform all elements of the steps array, you can use the following Jolt spec:
[
{
"operation": "shift",
"spec": {
"steps": {
"0": {
"start": "date[0].value",
"end": "date[1].value"
},
"*": {
"*": "steps[&1].&",
"#startDate": "date[0].name",
"#endDate": "date[1].name"
}
}
}
}
]
One option is to conditionally pick by the existing(steps) array's indexes while walking through it such as
[
{
"operation": "shift",
"spec": {
"steps": {
"#1": "",// derive the whole value from the upper level, eg. replicate it
"0": {// the first index
"#startDate": "date[&1].name",
"start": "date[&1].value"
},
"*": {// the other index(this case there's only one)
"#endDate": "date[&1].name",// bring the value of the wrapper object'S index by using &1(going up one level the tree)
"end": "date[&1].value"
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

Can I create Multiple arrays dynamically based on a key value with jolt?

I have a following JSON :
{
"timestamp": 1665923527,
"place": "us",
"event": "custom",
"Users": [
{
"email": "test1#test.com",
"key1": "Admin"
},
{
"email": "test2#test.com",
"key1": "Admin"
}
]
}
which I want to modify it to multiple array based on the users key dynamically. In the above example I have 2 arrays inside user. So I want the output to be:
[
{
"timestamp": 1665923527,
"place": "us",
"event": "custom",
"email": "test1#test.com",
"key1": "Admin"
},
{
"timestamp": 1665923527,
"place": "us",
"event": "custom",
"email": "test2#test.com",
"key1": "Admin"
}
]
Is it possible with Jolt?
I did search in all the documents i found, but no luck
You can walk through the attributes of the innermost array(Users) by using a shift transformation spec while copying the values of the others grabbed from after going two levels up the tree such as
[
{
"operation": "shift",
"spec": {
"Users": {
"*": {
"#(2,timestamp)": "[&1].timestamp", // go 2 levels up the tree to grab the value of timestamp by using "#(2,timestamp)", [&1] stands for going 1 level up to reach the level of "Users" array to combine all values at that level
"#(2,place)": "[&1].place",
"#(2,event)": "[&1].event",
"*": "[&1].&"
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is
Edit : alternatively you can prefer the below one to make it dynamic :
[
{
// separate the attributes into two groups "x" and "y"
"operation": "shift",
"spec": {
"Users": {
"*": {
"*": {
"#": "x.&2.&"
}
}
},
"*": "y.&"
}
},
{
// combine each attributes under common index values
"operation": "shift",
"spec": {
"x": {
"*": {
"#(2,y)": "&2.&"
},
"#": "&"
}
}
},
{
// dive deep into indexes
"operation": "shift",
"spec": {
"x": {
"*": {
"*": {
"*": "[&2].&"
}
}
}
}
}
]
the demo on the site http://jolt-demo.appspot.com/ is

Jolt transform: extract nested array from an object

I have JSON Input as below
{
"data": [
{
"items": [
{
"item": "R11",
"code": "8611A"
},
{
"item": "R2",
"code": "8611B"
}
]
}
]
}
I need to extract items array as below
[
{
"item": "R11",
"code": "8611A"
},
{
"item": "R2",
"code": "8611B"
}
]
Please copy and paste the above INPUT and OUTPUT https://jolt-demo.appspot.com/#inception
I have tested [{"operation":"shift","spec":{"data":{"*":""}}}]
But it returns {"items" : [ {...}, {...} ] }
You can use a shift transformation as below
[
{
"operation": "shift",
"spec": {
"*": { //might be replaced with "data"
"*": {
"*": //might be replaced with "items"
{
"#": ""
}
}
}
}
}
]
where the asterisks wildcards represent the array data, its indexes, and the array items respectively. The "#":"" represents the items as array of objects with no key.
Alternative Spec:
[
{
"operation": "shift",
"spec": {
"data": {
"*": {
"items": ""
}
}
}
}
]
Here is the answer
[{
"operation": "shift",
"spec": {
"data": {
"0": {
"*": ""
}
}
}
}]

How to take values from an array in JOLT, put them into an array of object values

For input
{
"field1": {
"array1": [
"a",
"b"
],
"array2": [
"c",
"d"
]
}
}
I want the output:
{
"objectArray": [
{
"role": "to",
"id": "a"
},
{
"role": "to",
"id": "b"
},
{
"role": "to",
"id": "c"
},
{
"role": "to",
"id": "d"
}
]
}
I currently am trying:
[
{
"operation": "shift",
"spec": {
"field1": {
"array1": {
"#to": "objectArray[].role",
"#": "objectArray[].id"
},
"array2": {
"#to": "objectArray[].role",
"#": "objectArray[].id"
}
}
}
}
]
However this seems to separate out the roles and ids into their own separate objects, after the first one.
You can use this two step of shift transformation spec.
[
{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": "o[].id"
}
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": {
"*": "objectArray[&1].&",
"#to": "objectArray[&1].role"
}
}
}
}
]
where you got and array for all ids in the first step, and then adding an arbitrarily chose key-value pairs within the second step while renaming the target array

JSON to JSON transformation on keys using Jolt

Jolt newbie here! I would like to transform a JSON input from this template:
[
{
"canalId": "",
"startDate": "",
"typeCanal": "",
"origin": "",
"principal": false,
"ligne1": "",
"ligne2": "",
"ligne4": "",
"ligne6": ""
},
{
...
}
]
to the same template, only with some keys changing names:
[
{
"id_canal": "",
"startDate": "",
"media": "",
"origin": "",
"principal": false,
"adrL1": "",
"adrL2": "",
"adrL3": "",
"adrL4": ""
},
{
...
}
]
So far, I managed to either use this spec:
[
{
"operation": "shift",
"spec": {
"*": {
"canalId": "&1.id_canal",
"typeCanal": "&1.media",
//More if needed
"*": "&1.&"
}
}
}
]
But it returns me some indexes that I don't need, plus I would like to keep the fact that it is a Json Array, aka the square brackets.
Or this one but it requires a split on the incoming JSON to deal only with parts of it:
[
{
"operation": "shift",
"spec": {
"canalId": "id_canal",
"typeCanal": "media",
// More if needed
"*": "&"
}
}
]
But in that case, I would like it to become a JSON array and not just a JSON object.
I am using all of this in a Camel route as it is the requirement, is there any Spec I could use that would do the trick? Or maybe another idea based on Camel itself?
Thanks in advance!
Adding an extra shift following yours would do the trick:
[
{
"operation": "shift",
"spec": {
"*": {
"canalId": "&1.id_canal",
"typeCanal": "&1.media",
//More if needed
"*": "&1.&"
}
}
},
{
"operation": "shift",
"spec": {
"*": {
"*": "[&1].&"
}
}
}
]

Categories