Scripted REST API returning only 1 result

JTM201
Tera Expert

My scripted REST API only returns one result. When I run as a background script and stringify the object, I see all of the results. Im not limiting the results at all in the API so there must be something in the code. 

 

 

EDIT: I believe I figured this out. I need to clear the variableName and variablesObject at the end of the loop so when it loops back through with another incident, it has an empty variables object. Thanks everyone. Working code below:

 

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // implement resource here
    var variableName,
        i,
        incidentVariables = [],
        catalog_sys,
        inc, 
		variablesObject = {},
        inc_number = [],
        arr = [],
        responseObj = {}; //The object that should ultimately be returned.

    catalog_sys = request.getHeader('catalog');

    inc = new GlideRecord('sc_item_produced_record');
    inc.addQuery('producer', catalog_sys);
    inc.query();
    while (inc.next()) {
        inc_number.push(inc.task.number);
    }
    for (i = 0; i < inc_number.length; i++) {
        var inc_table = new GlideRecord('incident');
        inc_table.addQuery('number', inc_number[i]);
        inc_table.query();
        while (inc_table.next()) {
            incidentVariables = inc_table.variables;
            //variablesObject["number"] = inc_number[i].toString();
            for (variableName in incidentVariables) {
                if (incidentVariables.hasOwnProperty(variableName) && incidentVariables[variableName]) { //Make sure the property exists and isn't null or unknown.
                    variableName = variableName.toString(); //Make sure we're all proper strings here.
                    variablesObject[variableName] = incidentVariables[variableName].getDisplayValue().toString();
                }
            }
        }
        responseObj = addObjToObj(responseObj, variablesObject, inc_number[i].toString());
        arr.push(responseObj);
        variableName = "";
        variablesObject = {};
    }
    return arr;

    //Helper function below
    function addObjToObj(parent, child, name) {
        parent[name] = child;
        return parent; //Note: Does not break pass-by-reference, because we're declaring a new object on each loop on line 39 above.
    }

})(request, response);

 

1 ACCEPTED SOLUTION

JTM201
Tera Expert

 I believe I figured this out. I need to clear the variableName and variablesObject at the end of the loop so when it loops back through with another incident, it has an empty variables object. Thanks everyone. Working code below:

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // implement resource here
    var variableName,
        i,
        incidentVariables = [],
        catalog_sys,
        inc, 
		variablesObject = {},
        inc_number = [],
        arr = [],
        responseObj = {}; //The object that should ultimately be returned.

    catalog_sys = request.getHeader('catalog');

    inc = new GlideRecord('sc_item_produced_record');
    inc.addQuery('producer', catalog_sys);
    inc.query();
    while (inc.next()) {
        inc_number.push(inc.task.number);
    }
    for (i = 0; i < inc_number.length; i++) {
        var inc_table = new GlideRecord('incident');
        inc_table.addQuery('number', inc_number[i]);
        inc_table.query();
        while (inc_table.next()) {
            incidentVariables = inc_table.variables;
            //variablesObject["number"] = inc_number[i].toString();
            for (variableName in incidentVariables) {
                if (incidentVariables.hasOwnProperty(variableName) && incidentVariables[variableName]) { //Make sure the property exists and isn't null or unknown.
                    variableName = variableName.toString(); //Make sure we're all proper strings here.
                    variablesObject[variableName] = incidentVariables[variableName].getDisplayValue().toString();
                }
            }
        }
        responseObj = addObjToObj(responseObj, variablesObject, inc_number[i].toString());
        arr.push(responseObj);
        variableName = "";
        variablesObject = {};
    }
    return arr;

    //Helper function below
    function addObjToObj(parent, child, name) {
        parent[name] = child;
        return parent; //Note: Does not break pass-by-reference, because we're declaring a new object on each loop on line 39 above.
    }

})(request, response);

View solution in original post

12 REPLIES 12

Can you please share what result you are getting now and what is expected? you can reduce variables for the sake of simplicity.

 

Thanks,
Anil Lande 

Please appreciate the efforts of community contributors by marking appropriate response as correct answer and helpful, this may help other community users to follow correct solution in future.
Thanks
Anil Lande

Abhijit4
Mega Sage

Hi,

Yes, your code will always return only last record information. To get all record details, you would need to store your 'responseObj' object in another array as shown something like below,

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // implement resource here
    var variableName, i, incidentVariables, catalog_sys, inc, variablesObject,
        inc_number = [];
    var responseObj = {}; //The object that should ultimately be returned.
    var responseObjArray=[];
    catalog_sys = request.getHeader('catalog');

    if (!catalog_sys) {
        //If ritm header was not set or was malformed, return an error.
        response.setStatus(417);
        return 'Unable to process request. Request header \'catalog\' not defined. ' +
            'Please define a request header called \'catalog\' with the value set to the sys_id for the catalog RITMs you\'d like to retrieve the variables for. Value provided for Catalog: ' +
            catalog_sys;
    }

    inc = new GlideRecord('sc_item_produced_record');
    inc.addQuery('producer', catalog_sys);
    inc.query();
    while (inc.next()) {
        inc_number.push(inc.task.number);
    }

    for (i = 0; i < inc_number.length; i++) {
        var inc_table = new GlideRecord('incident');
        inc_table.addQuery('number', inc_number[i]);
        inc_table.query();
        while (inc_table.next()) {
            incidentVariables = inc_table.variables;
            //Declare a fresh object each loop.
            //This will be made to contain all of the variables and variable values for the RITM we're iterating over,
            //Then it will be pushed into the responseObj object, and reset for the next RITM on the next iteration.
            variablesObject = {};
            //Set the 'number' property on the variables object to the current ritm number. This will also be the
            variablesObject["number"] = inc_table.number + "";
            //Iterate over incidentVariables, looping through each one as v.
            //This is necessary because the "gr.variables" is not a standard JS object, and cannot be mapped.
            for (variableName in incidentVariables) {
                //NOTE: If you want to return all variables on the catalog item associated with the RITM, remove the second condition in the IF block below.
                //With the second condition, this will only show variables that have been populated.
                if (incidentVariables.hasOwnProperty(variableName) && incidentVariables[variableName]) { //Make sure the property exists and isn't null or unknown.
                    variableName = variableName.toString(); //Make sure we're all proper strings here.
                    //pushing the variable into variablesObject, which will be copied into responseObject along with a version of variablesObject for each of the RITMs.
                    variablesObject[variableName] = incidentVariables[variableName].getDisplayValue().toString();
                }

            }
            //Call addObjToObj function to add variablesObject to responseObj with the key set to the current RITM number, so it can be accessed as 'responseObj["RITM0123456"]'.
            //NOTE: If we didn't use addObjToObj, we'd run into this problem where objects are linked rather than copied, when added to other objects in javascript.
            responseObj = addObjToObj(responseObj, variablesObject, inc.producer.name);
            responseObjArray.push(responseObj);
        }
        gs.log(JSON.stringify(responseObjArray));
        return responseObjArray; //Returning the variables and their values. Returning an object here will set the response "body" to the JSON equivalent of this object.

    }

    //Helper function below
    function addObjToObj(parent, child, name) {
        parent[name] = child;
        return parent; //Note: Does not break pass-by-reference, because we're declaring a new object on each loop on line 39 above.
    }
})(request, response);

Now what we are doing is, we are storing each object in another array where we will get all records in the array at the end.

Please mark this as Correct or Helpful if it helps.

Thanks and Regards,
Abhijit
Community Rising Star 2022

 

By marking my response as correct or helpful, you contribute to helping future readers with similar issues.
Regards,
Abhijit
ServiceNow MVP

Thanks, I did try that, and it does return all data in a single object, but it just repeats the same variables over and over for each incident. Here is a more condensed version of the code and the result. 

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // implement resource here
    var  variableName, i, incidentVariables = [],
        catalog_sys,
        inc, variablesObject = {},
        inc_number = [],
        arr = [];
    var responseObj = {}; //The object that should ultimately be returned.
    catalog_sys = request.getHeader('catalog');

    inc = new GlideRecord('sc_item_produced_record');
    inc.addQuery('producer', catalog_sys);
    inc.query();
    while (inc.next()) {
        inc_number.push(inc.task.number);
    }

    for (i = 0; i < inc_number.length; i++) {
        var inc_table = new GlideRecord('incident');
        inc_table.addQuery('number', inc_number[i]);
        inc_table.query();
        while (inc_table.next()) {
            incidentVariables = inc_table.variables;
            //variablesObject["number"] = inc_number[i].toString();
            for (variableName in incidentVariables) {
                if (incidentVariables.hasOwnProperty(variableName) && incidentVariables[variableName]) { //Make sure the property exists and isn't null or unknown.
                    variableName = variableName.toString(); //Make sure we're all proper strings here.
                    variablesObject[variableName] = incidentVariables[variableName].getDisplayValue().toString();
                }
            }
        }
        responseObj = addObjToObj(responseObj, variablesObject, inc_number[i].toString());
        arr.push(responseObj);
    }
    return arr;

    //Helper function below
    function addObjToObj(parent, child, name) {
        parent[name] = child;
        return parent; //Note: Does not break pass-by-reference, because we're declaring a new object on each loop on line 39 above.
    }

})(request, response);

Result: 

{
    "result": [
        {
            "INC0074987": {
                "u_client_impact": "Individual",
                "u_client_urgency": "Non-urgent",
                "company": "AI4 Process Ltd.",
                "caller_id": "SS&C Contact - Ai4P ",
                "assignment_group": "APC Support",
                "u_client_environment": "Production",
                "u_occurred_date": "10/19/2021",
                "short_description": "test",
                "description": "fgjhd",
                "u_number_of_users": "5",
                "u_steps_to_recreate": "kkkkkkk",
                "u_route_in": "Portal"
            },
            "INC0075295": {
                "u_client_impact": "Individual",
                "u_client_urgency": "Non-urgent",
                "company": "AI4 Process Ltd.",
                "caller_id": "SS&C Contact - Ai4P ",
                "assignment_group": "APC Support",
                "u_client_environment": "Production",
                "u_occurred_date": "10/19/2021",
                "short_description": "test",
                "description": "fgjhd",
                "u_number_of_users": "5",
                "u_steps_to_recreate": "kkkkkkk",
                "u_route_in": "Portal"
            },
            "INC0075697": {
                "u_client_impact": "Individual",
                "u_client_urgency": "Non-urgent",
                "company": "AI4 Process Ltd.",
                "caller_id": "SS&C Contact - Ai4P ",
                "assignment_group": "APC Support",
                "u_client_environment": "Production",
                "u_occurred_date": "10/19/2021",
                "short_description": "test",
                "description": "fgjhd",
                "u_number_of_users": "5",
                "u_steps_to_recreate": "kkkkkkk",
                "u_route_in": "Portal"
            },
            "INC0076020": {
                "u_client_impact": "Individual",
                "u_client_urgency": "Non-urgent",
                "company": "AI4 Process Ltd.",
                "caller_id": "SS&C Contact - Ai4P ",
                "assignment_group": "APC Support",
                "u_client_environment": "Production",
                "u_occurred_date": "10/19/2021",
                "short_description": "test",
                "description": "fgjhd",
                "u_number_of_users": "5",
                "u_steps_to_recreate": "kkkkkkk",
                "u_route_in": "Portal"
            },

Please try below:

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // implement resource here
    var  variableName, i, incidentVariables = [],
        catalog_sys,
        inc, variablesObject = {},
        inc_number = [],
        arr = [];
    var responseObj = {}; //The object that should ultimately be returned.
    catalog_sys = request.getHeader('catalog');

    inc = new GlideRecord('sc_item_produced_record');
    inc.addQuery('producer', catalog_sys);
    inc.query();
    while (inc.next()) {
        inc_number.push(inc.task.number);
    }

    for (i = 0; i < inc_number.length; i++) {
        var inc_table = new GlideRecord('incident');
        inc_table.addQuery('number', inc_number[i]);
        inc_table.query();
        if(inc_table.next()) {
incidentVariables = [];  // reset incidentVariables in every iteration
            incidentVariables = inc_table.variables;
            variablesObject={};  // reset variablesObject in every iteration
            for (variableName in incidentVariables) {
                if (incidentVariables.hasOwnProperty(variableName) && incidentVariables[variableName]) { //Make sure the property exists and isn't null or unknown.
                    variableName = variableName.toString(); //Make sure we're all proper strings here.
                    variablesObject[variableName] = incidentVariables[variableName].getDisplayValue().toString();
                }
            }
        }
        responseObj = addObjToObj(responseObj, variablesObject, inc_number[i].toString());
        arr.push(responseObj);
    }
    return arr;

    //Helper function below
    function addObjToObj(parent, child, name) {
        parent[name] = child;
        return parent; //Note: Does not break pass-by-reference, because we're declaring a new object on each loop on line 39 above.
    }

})(request, response);

 

Thanks,

Anil Lande

Please appreciate the efforts of community contributors by marking appropriate response as correct answer and helpful, this may help other community users to follow correct solution in future.
Thanks
Anil Lande