0

I have a dataframe. I need to call a Rest API for each record.

Lets say the Dataframe looks like:

|----|-------------|-----|---------|
|UUID|PID          |DEVID|FIRSTNAME|
|----|-------------|-----|---------|
|1111|1234567891011|ABC11|JOHN     |
|2222|9876543256827|ABC22|HARRY    |
|----|-------------|-----|---------|

The JSON request string for first row should look like(Note: the json is created on 2 columns, not all), as the Rest API to be called requires the input in this format:

{"applicationInfo": {"appId": "ec78fef4-92b9-3b1b-a68d-c45376b6977a"}, "requestData": [{"secureData": "JOHN", "secureDataType": "FIRSTNAME", "index": 1 }, {"secureData": "1234567891011", "secureDataType": "PID", "index": 2 } ] }

The value of index key has to be generted on the fly, using an incremental counter for each row.

Then, i need to call the Rest API sending the above JSON as a string param.

The response from the API after encryption will look like:

{"responseData":[{"resultCode":"00","secureData":"63ygdydshbhgvdyw3et7edgu","secureDataType":"FIRSTNAME","index":1},{"resultCode":"00","secureData":"HKJJBJHVHG66456456FXXFFCGF","secureDataType":"PID","index":2}],"responseCode":"00","responseMessage":"SUCCESS","resultCounts":{"totalCount":2,"successCount":2,"failedCount":0}}

Then I need to read the above response and create a dataframe which should look like:

|----|--------------------------|-----|------------------------|
|UUID|PID                       |DEVID|FIRSTNAME               |
|----|--------------------------|-----|------------------------|
|1111|HKJJBJHVHG66456456FXXFFCGF|ABC11|63ygdydshbhgvdyw3et7edgu|
|----|--------------------------|-----|------------------------|

If i convert the initial input dataframe toJSON().collectAsList(), then it looks like:

[{"UUID":"1111","PID":"1234567891011","DEVID":"ABC11","FIRSTNAME":"JOHN"}, {"UUID":"2222","PID":"9876543256827","DEVID":"ABC22","FIRSTNAME":"HARRY"}]

But this doesnt work as the Rest API requires its input in a certain format, mentioned above. Please help.

1 Answer 1

1

For the above, I assume that the data set has been partitioned across the number of Spark workers and it is a generic data set of Row (data frame), then the below mechanism can be employed.

  1. Define a class with the required attributes as a data container
  2. Take the data set content as a List (takeAsList method if data set, refer)
  3. Create and populate the objects of your data container (and store in such a way to identify them later, you shall have to repopulate them with decrypted data)
  4. Serialize the list into a JSON array with Jackson (refer) Step 4 & 5 can be combined with Jackson custom serializer refer example
  5. Make the REST call and repopulate the data container objects (after deserializing the response with Jackson)
  6. Create a data frame (an example)
  7. Process the data frame (dataset of rows)

NOTE: The JSON structure you have provided seems not to be correct, JSON array is [{},{},{}]


In your case, given the format of the request JSON, direct conversion of rows will not work, as mentioned in point 1, make a set of model classes, you could consider the below model classes.

package org.test.json;

import java.util.List;

public class RequestModel {

protected ApplicationInfo applicationInfo;
protected List<RequestData> requestData;

public ApplicationInfo getApplicationInfo() {return applicationInfo;}
public void setApplicationInfo(ApplicationInfo applicationInfo) {this.applicationInfo = applicationInfo;}

public List<RequestData> getRequestData() {return requestData;}
public void setRequestData(List<RequestData> requestData) {this.requestData = requestData;}

}//class closing




package org.test.json;

public class ApplicationInfo {

protected String appId;

public String getAppId() {return appId;}
public void setAppId(String appId) {this.appId = appId;}

}//class closing




package org.test.json;

public class RequestData {

protected String secureData;
protected String secureDataType;
protected int index;

public String getSecureData() {return secureData;}
public void setSecureData(String secureData) {this.secureData = secureData;}

public String getSecureDataType() {return secureDataType;}
public void setSecureDataType(String secureDataType) {this.secureDataType = secureDataType;}

public int getIndex() {return index;}
public void setIndex(int index) {this.index = index;}

}//class closing

Process the list as obtained from the data frame and populate the model classes and then convert with Jackson to get the request JSON.


The below should do what you are looking for, don't directly run this, the data set is null

        //Do not run this, will generate NullPointer, for example only
    Dataset<Row> ds=null;
    List<Row> rows=ds.collectAsList();

    RequestModel request=new RequestModel();

    //Set application id
    ApplicationInfo appInfo=new ApplicationInfo();
    appInfo.setAppId("some id");
    request.setApplicationInfo(appInfo);

    List<RequestData> reqData=new ArrayList<>();
    for(int i=0;i<rows.size();i++) {

        //Incrementally generated for each row
        int index=i;

        Row r=rows.get(i);
        int rowLength=r.size();

        for(int j=0;j<rowLength;j++) {

            RequestData dataElement=new RequestData();
            dataElement.setIndex(index);

            switch(j) {

                case 1:{dataElement.setSecureData(r.getString(j));dataElement.setSecureDataType("PID");break;}
                case 3:{dataElement.setSecureDataType(r.getString(j));dataElement.setSecureDataType("FIRSTNAME");break;}
                default:{break;}

            }//switch closing

            reqData.add(dataElement);

        }//for closing

    }//for closing
Sign up to request clarification or add additional context in comments.

7 Comments

Edited the Qs as per my requirement. Please take a look.
Please review my answer section, i have updated the code, but the list is getting overwritten
Added, the loop to populate the data.
This will not work because i am not reading all the columns, i only want to read 2 columns out of the 4 cols. And my first and second cols not necessarily will have PID and FIRSTNAME. Also you are not adding reqData to request(RequestModel) anywhere
I added the line just before the end of second for loop. request.setRequestData(reqData); } Then printed out the result: for(RequestData reqD:request.getRequestData()){ System.out.println( reqD.getSecureData()+" "+reqD.getSecureDataType()+" "+reqD.getIndex()); } Result: null null 0 1234567891011 PID 0 null null 0 null FIRSTNAME 0 null null 1 9876543256827 PID 1 null null 1 null FIRSTNAME 1
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.