skip to Main Content

I am trying to replace API Data with "All" in Emp_Id field in data in json. And then make rows with every data of API.
I tried in ecmascript but I need in Java as this map function is giving error in nifi.

API DATA: I have stored this data in "Response" attribute in ExtractText in Apache Nifi.

response 
{
    "status": "success",
    "data": [[123, 0], [124, 0], [446, 0], [620, 0], [470 ,1]]
};

jsonData
{
    "Emp_Id": "All",
    "Emp_loc": "523",
    "Emp_dept": "Management",
    "Emp_sub_dept": "Finance",
    "Emp_sub_dept2": "Accountant"
};

Expected Result

[
{
"Emp_Id":"123",
"Emp_loc":"523",
"Emp_dept":"Management",
"Emp_sub_dept":"Finance",
"Emp_sub_dept2":"Accountant"
},
{
"Emp_Id":"124",
"Emp_loc":"523",
"Emp_dept":"Management",
"Emp_sub_dept":"Finance",
"Emp_sub_dept2":"Accountant"
},
{
"Emp_Id":"446",
"Emp_loc":"523",
"Emp_dept":"Management",
"Emp_sub_dept":"Finance",
"Emp_sub_dept2":"Accountant"
},
{
"Emp_Id":"620",
"Emp_loc":"523",
"Emp_dept":"Management",
"Emp_sub_dept":"Finance",
"Emp_sub_dept2":"Accountant"
},
{
"Emp_Id":"470",
"Emp_loc":"523",
"Emp_dept":"Management",
"Emp_sub_dept":"Finance",
"Emp_sub_dept2":"Accountant"
}
]

This is tried in ecmaScript but I want it to be in Java because these functions are not working in executeScript of NIFI and giving error."java.lang.assertionError: geberating bytecode". Or if any other approach for converting this data.

this is the script I tried

var InputStreamCallback = Java.type("org.apache.nifi.processor.io.InputStreamCallback")
var IOUtils = Java.type("org.apache.commons.io.IOUtils");
var OutputStreamCallback =  Java.type("org.apache.nifi.processor.io.OutputStreamCallback");
var StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
var Set = Java.type("java.util.HashSet");
var Map = Java.type("java.util.HashMap");
var String = Java.type("java.lang.String");

var flowFile = session.get();
    
if (flowFile != null) {  
    var text = ''
    session.read(flowFile,
    new InputStreamCallback(function (inputStream) {
    text = IOUtils.toString(inputStream, StandardCharsets.UTF_8);             
}));

var s3Data ={}
var apiResponse={}
var map = new Map();
    
var s3Data = JSON.parse(flowFile.getAttribute('jsonData'))
var apiResponse = JSON.parse(flowFile.getAttribute('response'))

var result = apiResponse.data.map(([id]) =>
Object.fromEntries(Object.entries(s3Data).map(([k, v]) =>
[k, v === "All" ? id : v]
))
);  
flowFile = session.write(flowFile,
    new OutputStreamCallback(function(outputStream) {
    outputStream.write(JSON.stringify(result).getBytes(StandardCharsets.UTF_8))
})
);
}

I tried with groovy also but I have very less knowledge of Groovy so I couldn’t write the proper ExecuteScript.

2

Answers


  1. Can you try following Code, please see that i have trie to match the output if there are anyother logic present please update question.

    ObjectMapper from here

    //Reading data from file into string variable if this is stream then it becomes more easy
    File dataFile = ResourceUtils.getFile("classpath:data.json");
                    File templateFile = ResourceUtils.getFile("classpath:template.json");
                    String filesData = Files.readString(Path.of(dataFile.toURI()));
                    String templatesData = Files.readString(Path.of(templateFile.toURI()));
    
                    InputData inputData = objectMapper.readValue(filesData, InputData.class);
    
                    System.out.println(inputData);
    
                    List<Template> collect = Arrays.stream(inputData.data)//stream data array
                            .map(item -> Arrays.stream(item).findFirst()) find the first item from the 2d array
                            .map(OptionalInt::orElseThrow)//get first int or throw and exception
                            .map(optionalInt -> {
    //Map the tempalte to pojo class and replace items
                                try {
                                    final Template template = objectMapper.readValue(templatesData, Template.class);
                                    template.setEmpId(String.valueOf(optionalInt));
                                    return template;
                                } catch (JsonProcessingException e) {
                                    throw new RuntimeException(e);
                                }
                            })
                            .collect(Collectors.toList());
                    System.out.println(objectMapper.writeValueAsString(collect));
    
    Login or Signup to reply.
  2. You may try library Josson & Jossons to transform and join the two datasets.

    https://github.com/octomix/josson

    Deserialize, Transform and Join

    Left join <=< two transformed datasets with matching key.

    Josson response = Josson.fromJsonString(
        "{" +
        "    "status": "success"," +
        "    "data": [[123, 0], [124, 0], [446, 0], [617, 1], [620, 0], [470 ,1]]" +
        "}");
    Josson jsonData = Josson.fromJsonString(
        "{" +
        "    "Emp_Id": "All"," +
        "    "Emp_loc": "523"," +
        "    "Emp_dept": "Management"," +
        "    "Emp_sub_dept": "Finance"," +
        "    "Emp_sub_dept2": "Accountant"" +
        "}");
    JsonNode node = new Jossons()
        .putDataset("response", response)
        .putDataset("jsonData", jsonData)
        .evaluateQuery("response->data@.[0].map(Emp_Id:?,key:'All'){key} <=< jsonData->field(key:Emp_Id,Emp_Id:){key}");
    System.out.println(node.toPrettyString());
    

    Output

    [ {
      "Emp_Id" : 123,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    }, {
      "Emp_Id" : 124,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    }, {
      "Emp_Id" : 446,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    }, {
      "Emp_Id" : 617,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    }, {
      "Emp_Id" : 620,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    }, {
      "Emp_Id" : 470,
      "key" : "All",
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant"
    } ]
    

    Demonstrate the transformation of response

    Divert each data element to separate branches. For each branch, get the first array element and then build an object with element Emp_Id and key.

    JsonNode node = response.getNode("data@.[0].map(Emp_Id:?,key:'All')");
    System.out.println(node.toPrettyString());
    

    Output

    [ {
      "Emp_Id" : 123,
      "key" : "All"
    }, {
      "Emp_Id" : 124,
      "key" : "All"
    }, {
      "Emp_Id" : 446,
      "key" : "All"
    }, {
      "Emp_Id" : 617,
      "key" : "All"
    }, {
      "Emp_Id" : 620,
      "key" : "All"
    }, {
      "Emp_Id" : 470,
      "key" : "All"
    } ]
    

    Demonstrate the transformation of jsonData

    Add an element key with the value of Emp_Id and then remove Emp_Id.

    JsonNode node = jsonData.getNode("field(key:Emp_Id,Emp_Id:)");
    System.out.println(node.toPrettyString());
    

    Output

    {
      "Emp_loc" : "523",
      "Emp_dept" : "Management",
      "Emp_sub_dept" : "Finance",
      "Emp_sub_dept2" : "Accountant",
      "key" : "All"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search