I want to achieve the below request-response scenario in Nifi. My objective is to use each value coming as an array(object key 1,object key 2,...) in further differt processors.
So if I can convert it into multiple JSON, then using split JSON I can use multiple vales later.
Please suggest all sorts of solution for this.
Input JSON:
[
{
"ID": "789654",
"Date": "29th Feb",
"Key" : ["object key 1", "object key 2", "object key 3"....]
}
]
Output JSON:
[
{
"ID": "789654",
"Date": "29th Feb",
"Key1" : "object key 1"
},
{
"ID": "789654",
"Date": "29th Feb",
"Key2" : "object key 2"
},
{
"ID": "789654",
"Date": "29th Feb",
"Key3" : "object key 3"
},
.
.
.
.
.
.
]
you have two levels array. i assume in the root array you could have several objects
[
{
"ID" : "111",
"Date" : "29th Feb",
"Key" : ["object key 1", "object key 2", "object key 3", "object key 4"]
},
{
"ID" : "222",
"Date" : "27th Feb",
"Key" : ["object key 5", "object key 6"]
}
]
use the following flow
- SplitJson - split file by a root array
$
- EvaluateJsonPath - extract
$.ID
and $.Date
values into attributes with corresponding names
- SplitJson - split files by
$.Key
- ReplaceText - the result of previous step is non-valid json because you have an array of strings in
Key
. you have to wrap string in content with doublequotes: (?s)(^.*$)
-> "$1"
- EvaluateJsonPath - extract string from context
$
into Key
attribute
- AttributesToJson - the last step to build json from attributes
extremely alternative variant
Use ExecuteGroovyScript
with script:
@Grab(group='acme.groovy', module='acmenifi', version='20190218')
import static groovyx.acme.nifi.AcmeNiFi.*
withFlowFile(this).withJson{json,attr->
json.each{o1->
o1.Key.each{k1->
//build new file with json
newFlowFile(this).withJson{json2,attr2->
attr2.putAll(attr)
return o1 + [Key:k1] //set content of new flow file
}
}
}
return null //drop current file
}
You can use the .map
function on the Key
property of each one of the items of the input JSON.
The following will output the desired result for the first input value. You can then iterate through each of the input objects.
const result = input[0].Key.map((key) => {return {ID: input[0].ID, Date: input[0].Date, Key: key}});