The CreatorCon Call for Content is officially open! Get started here.

JSON cannot read property from undefined

Wilwod
Tera Expert

Hi there, 

 

I am getting an undefined error when trying to look at a JSON payload. 

 

The payload is built in the same script, and to debug I am trying to call the name of the payload to check that the name of the CI can be used. 

 

This is my test script: 

 

        var ax = new GlideRecord('x_ccluk_axonious_axonious_api');
        ax.addEncodedQuery();
        ax.setLimit(1);
        ax.query();
        gs.info("MigrateUTIL [6] run");

        while (ax.next()) {
            try {
                var lastDiscovered = new GlideDateTime(ax.u_most_recent_discovery);
                var os = ax.u_os_edition.toString().trim() != "" ? ax.u_operating_system.toString() + ' ' + ax.u_os_edition.toString() : ax.u_operating_system.toString();
                var fqdn = ax.u_fqdn_host_name;
                var className = ax.u_class.toString();
                var payload = {
                    "items": [{
                        "className": className,
                        "values": {
                            'name': ax.u_name.toString(),
                            'serial_number': ax.u_serial_number.toString(),
                            'manufacturer': ax.u_manufacturer.toString(),
                            //'fqdn': this.isValidFQDN(fqdn) ? fqdn : '',
                            'model_id': ax.u_model_id.toString(),
                            'os': os,
                            'os_version': ax.u_os_version.toString(),
                            'ip_address': ax.u_ip_address.toString(),
                            'mac_address': ax.u_mac_address.toString(),
                            'last_discovered': lastDiscovered.toString(),
                            'install_date': ax.u_first_seen.toString(),
                            'install_status': '1',
                            'company': ax.u_company.toString()
                        }
                    }]
                };
                gs.info("MigrateUTIL [34] run");
                var parser = new global.JSONParser();
				var parsed = parser.parse(payload);
				var ciName = parsed.items[0].values[0].name;
				gs.info(ciName);
                // var ci_sys_id;
                // gs.info("MigrateUTIL [37] run");
                // var inputPayload = new global.JSON().encode(payload); //JSON formatted string
                // gs.info("MigrateUTIL [39] run");
                // gs.info(payload.items.values.ip_address);

            } catch (error) {
                gs.error("Axonius migrate error: " + error.message);
            }
        }

Which outputs

x_ccluk_axonious: MigrateUTIL [6] run
x_ccluk_axonious: MigrateUTIL [34] run
x_ccluk_axonious: Axonius migrate error: Cannot read property "0" from undefined

 

I have been testing with this code for a few days and have not had any luck yet, so help would be really appreciated. 

 

This is a scoped application, and the idea would be to then use the IRE API to feed the data into the CMDB, however the payload gets loaded with data, but cannot be called into the IRE Scripts in the live code, below:

 

var AxoniusAPIMigrateUtil = Class.create();
AxoniusAPIMigrateUtil.prototype = {
    initialize: function() {

    },

    isValidFQDN: function(fqdn) {

        var fqdnPattern = /^(?=.{1,253}$)(([A-Za-z0-9]+(-[A-Za-z0-9]+)*\.)+[A-Za-z]{2,63})$/;
        return fqdnPattern.test(fqdn);
    },

    migrateByBrandLatestImportSet: function(brand) {
        gs.info("MigrateUTIL [14] run");
        var importSet = '';
        var axoimp = new GlideRecord('x_ccluk_axonious_axonious_api');
        axoimp.addEncodedQuery();
        axoimp.orderByDesc('u_import_set_id');
        axoimp.setLimit(1);
        axoimp.query();

        while (axoimp.next()) {
            importSet = axoimp.u_import_set_id.getDisplayValue();
        }

        var ax = new GlideRecord('x_ccluk_axonious_axonious_api');
        ax.addQuery('u_import_set_id.number', importSet);
        ax.addEncodedQuery("u_classISNOTEMPTY^u_class!=N/A^u_class!=NULL");
        ax.query();
        gs.info("MigrateUTIL [28] run");

        while (ax.next()) {
            try {
                var lastDiscovered = new GlideDateTime(ax.u_most_recent_discovery);
                var os = ax.u_os_edition.toString().trim() != "" ? ax.u_operating_system.toString() + ' ' + ax.u_os_edition.toString() : ax.u_operating_system.toString();
                var fqdn = ax.u_fqdn_host_name;
                var className = ax.u_class.toString();
                var payload = {
                    "items": [{
                        "className": className,
                        "values": {
                            'name': ax.u_name.toString(),
                            'serial_number': ax.u_serial_number.toString(),
                            'manufacturer': ax.u_manufacturer.toString(),
                            'fqdn': this.isValidFQDN(fqdn) ? fqdn : '',
                            'model_id': ax.u_model_id.toString(),
                            'os': os,
                            'os_version': ax.u_os_version.toString(),
                            'ip_address': ax.u_ip_address.toString(),
                            'mac_address': ax.u_mac_address.toString(),
                            'last_discovered': lastDiscovered.toString(),
                            'install_date': ax.u_first_seen.toString(),
                            'install_status': '1',
                            'company': ax.u_company.toString()
                        }
                    }]
                };
                gs.info("MigrateUTIL [55] run");

                // if (className == "cmdb_ci_esx_server") {
                //     payload.items[0].values.correlation_id = 'ax.u_correlation_id';
                // }

                var ci_sys_id;
				gs.info("MigrateUTIL [62] run");
                var inputPayload = new global.JSON().encode(payload);//JSON formatted string
				gs.info("MigrateUTIL [64] run");
				gs.info(payload);
                var identifyJson = sn_cmdb.IdentificationEngineScriptableApi.identifyCI(inputPayload);
                var identify = global.JSON.parse(identifyJson);
                var operation = identify.items[0].operation;
                gs.info("MigrateUTIL [68] run");
                if (operation == 'UPDATE') {
                    gs.info("MigrateUTIL [78] run");
                    var cmdbgr = new GlideRecord('cmdb_ci');
                    cmdbgr.get(identify.items[0].sysId);

                    if (lastDiscovered > cmdbgr.last_discovered) {
                        sn_cmdb.IdentificationEngineScriptableApi.createOrUpdateCI('Axonius', inputPayload);
                        ci_sys_id = identify.items[0].sysId;
                        gs.info("Axnoius " + operation + ": " + identifyJson);
                        gs.info("MigrateUTIL [78] run");
                    }

                } else {
                    gs.info("MigrateUTIL [82] run");
                    var outputApi = sn_cmdb.IdentificationEngineScriptableApi.createOrUpdateCI('Axonius', inputPayload);
                    var output = global.JSON.parse(outputApi);
                    ci_sys_id = output.items[0].sysId;
                    gs.info("Axnoius migrate " + output.items[0].operation + ": " + outputApi);
                }
                // var ci_sys_id = output.items[0].sysId;

                if (ci_sys_id && ci_sys_id.length > 0 && ci_sys_id.toLowerCase() != 'unknown') {
                    gs.info("MigrateUTIL [91] run");
                    gs.info("Axonius script created / updated: " + ci_sys_id);
                    ax.u_related_ci = ci_sys_id;
                    ax.update();
                    // Update Created By/Updated By to user svc_Axonius 
                    // var cmdbGlideRecord = new GlideRecord('cmdb_ci');
                    // if(cmdbGlideRecord.get(ci_sys_id)) {
                    // cmdbGlideRecord.autoSysFields(false); 

                    // if (operation == 'UPDATE') {
                    // cmdbGlideRecord.sys_updated_by = 'svc_Axonius';

                    // } else {
                    // cmdbGlideRecord.sys_created_by = 'svc_Axonius';
                    // }

                    // cmdbGlideRecord.update();
                    // 
                }
            } catch (error) {
                gs.error("Axonius migrate error: " + error.message);
            }
        }
    },
    type: 'AxoniusAPIMigrateUtil'
};

The script will fail when this line is run and returns with the undefined error: 

var inputPayload = new global.JSON().encode(payload);//JSON formatted string

Thanks in advance !

2 ACCEPTED SOLUTIONS

Well the in the solution for that thread is stated that:

the property is already string so don't use JSON.stringify()

I used as I was testing in background script

So it was used just to simulate the situation where the data would be loaded from a property, where it would be a string.

 

As for IRE, I would look into Script Include global.CMDBTransformUtil which contains functions that allow you to utilize a regular transform map (and its fields maps) to build payloads and to consume those payloads. SN uses the functions in that Script Include when they want to import data into the CMDB through Import Set Row tables. E.g. S.C.C.M. integration used to use it.

All in all, once you figure out what the Script Include does, it can make your life easier as it will enable you to make the payloads "configurable".

View solution in original post

You're welcome, glad that it works!

As for the tomfoolery, probably just copied some not-printable/invisible Unicode character with the text 🙂

View solution in original post

8 REPLIES 8

-O-
Kilo Patron

For the 1st case, you are trying to parse an object which results in an undefined.

Objects are "stringify"-ed, strings are "parse"-ed.

You already have an object so why would you want to "convert" it into an object?

If you would have used JSON.parse (vs. new JSON().encode), you would have received a different error, while parsing which might have been enough of a hint for you to figure out what is going wrong.

E.g. running

gs.debug(JSON.parse({}))

results in error

Script execution error: Script Identifier: null.null.script, Error Description: Unexpected token: o, Script ES Level: 0
Evaluator: com.glide.script.RhinoEcmaError: Unexpected token: o
   script : Line(155) column(0)

because it ends up parsing string [object Object] - which is obviously not valid JSON.

So beware of new JS0N() - it just hides errors.

Hi -O- Thank you,

 

I have managed to get the values to pull from the payload now, it was the JSON payload structure that was causing some issues. 

  • value names should have been within double quotations (" ").
  • Commented out lines invalidated the payload.

I also converted the payload to a string and then parsed it back which set the payload correctly. 

var msg = global.JSON.stringify(payload);
var parsed = new global.JSON.parse(msg);

Here is my updated code that now correctly pulls this information:

var ax = new GlideRecord('x_ccluk_axonious_axonious_api');
ax.addEncodedQuery("u_classISNOTEMPTY^u_class!=N/A^u_class!=NULL");
ax.setLimit(1);
ax.query();
gs.info("MigrateUTIL [5] run");

while (ax.next()) {
    try {
        var lastDiscovered = new GlideDateTime(ax.u_most_recent_discovery);
        var os = ax.u_os_edition.toString().trim() != "" ? ax.u_operating_system.toString() + ' ' + ax.u_os_edition.toString() : ax.u_operating_system.toString();
        var fqdn = ax.u_fqdn_host_name;
        var className = ax.u_class.toString();
        var payload = [{
            "items": {
                "classname": className,
                "values": {
                    "name": ax.u_name.toString(),
                    "serial_number": ax.u_serial_number.toString(),
                    "manufacturer": ax.u_manufacturer.toString(),
                    "model_id": ax.u_model_id.toString(),
                    "os": os,
                    "os_version": ax.u_os_version.toString(),
                    "ip_address": ax.u_ip_address.toString(),
                    "mac_address": ax.u_mac_address.toString(),
                    "last_discovered": lastDiscovered.toString(),
                    "install_date": ax.u_first_seen.toString(),
                    "install_status": 1,
                    "company": ax.u_company.toString()
                }
            }
        }];

        var msg = global.JSON.stringify(payload);
        var parsed = global.JSON.parse(msg);

        for (var i = 0; i < parsed.length; i++) {
            break;
        }
        gs.info("Values CI Name: " + parsed[i].items.values.name);
        gs.info("_Class Name: " + parsed[i].items.classname);
        gs.info("MigrateUTIL [42] run");


    } catch (error) {
        gs.error("Axonius migrate error: " + error.message);
    }
}

 So far this is working for me. 

Sorry, but I gotta ask: what is the use of turning an object into a string and than back to how it was before: an object?

Other then perhaps getting back on ServiceNow by wasting process cycles/resources for nothing.

Have to say, not sure! I saw this solution in another thread here. But I can certainly do without that. 

 

Where I am also doing this in a scoped application, the IdentificationEngineScriptableApi is the incorrect use for that API, it should just be IdentificationEngine instead, so I need to test with this now. 

 

I ran the JSON through the IRE simulator and it works as expected and I know that the payload is now formatted correctly, I am close to a solution now.