Why does GlideRecord.getValue('field_name') return null for blank columns?

wfurman
Mega Contributor

//Using Eureka version - Background Scripts

var grContact = new GlideRecord('u_staging_ess_contacts');
if (grContact.get('u_first_name', 'Rachel')) {
  gs.print(grContact.getValue('u_mobile_phone'));   //returns null   (initially a blank string if viewed with the form)
  gs.print(grContact.getValue('u_home_phone'));   //returns a value XXX-XXX-XXX   (a non-blank value when viewed with the form)
  grContact.setValue('u_home_phone', grContact.getValue('u_mobile_phone'));
  grContact.update();
  gs.print(grContact.getValue('u_mobile_phone'));   //returns null
  gs.print(grContact.getValue('u_home_phone'));   //returns null   (but no update was actually made to the record)
}

//Then run this right after.....

var grContact = new GlideRecord('u_staging_ess_contacts');

if (grContact.get('u_first_name', 'Rachel')) {

  gs.print(grContact.getValue('u_mobile_phone'));   //returns null

  gs.print(grContact.getValue('u_home_phone'));   //returns original value XXX-XXX-XXX, field was not updated

}

/* Questions
u_home_phone is not updated, since it appears that setValue('u_home_phone', null) silently fails.
Why does grContact.getValue('u_mobile_phone') return a JavaScript null and not ''?   I started relying on setValue and getValue on the GlideRecord based on listening to a TechNow Server-Side Scripting video, but am beginning to doubt the validity of their use in all cases.

I switched to using grContact.u_mobile_phone.getDisplayValue(), but it would be nice to be consistent with getValue and setValue.   I don't want to have
to test the return value for null.   I need an easy API to move values between a normal table and a staging table for export where I don't have to worry about the type.

While I am at it - Why isn't the call GlideRecord.getDisplayValue('my_field_name') documented in GlideRecord.   It only documents returning the DisplayValue
for the record and not the specified field?   Is the documentation off?

*/

1 ACCEPTED SOLUTION

andrewkinca
ServiceNow Employee

Hi Wright!   I'm sorry that our TechNow video led you to a more frustrating experience.   If it makes you feel any better, I also do not like that getValue() returns null for an empty field (and for a non-existent field.)   While I cannot say why it is this way, it has been this way for a long time.   I can tell you what I typically do, although it is more code.



I either OR the getValue call with an empty string like:


var x = gr.getValue('something') || '';


Or, I use a custom getValueAK function that also supports dot-walking.   I usually include this function in the script itself, or I dump this into a Script Include:


// You can put this in a Script Include
// Features:
// - always returns a string
// - can dot-walk
// - returns empty string instead of null (for both empty fields and non-existent fields)
// - returns string 'true' or string 'false' for boolean fields
function getValueAK(field, ge) {

      // Local vars
      var fields;

      // If you don't pass in anything, you get an empty string
      if (!field) {
              return '';
      }

      // If no second parameter, assume this
      if (!ge) {
              ge = this;
      }

      // Split fields on dot
      fields = field.split('.');

      // If there is only one field
      if (fields.length === 1) {

              // If the field exists, return a string, else return empty string
              return ge[field] !== undefined ? String(ge[field]) : '';

      } else {

              // If there is more than one field, recurse
              return this.getValueAK(fields.slice(1).join("."), ge[fields.slice(0, 1)]);
      }

}

And you can use it like this:


var gr = new GlideRecord('incident');
gr.getValueAK = getValueAK;
gr.get('d71f7935c0a8016700802b64c67c11c6');
gs.print(gr.getValueAK('caller_id.manager.name'));

I hope this helps!


View solution in original post

6 REPLIES 6

I think there is a bug,   I am using a workaround that requires testing the value before sending it into setValue.   An enhancement request was submitted on my behalf.


andrewkinca
ServiceNow Employee

Hi Wright!   I'm sorry that our TechNow video led you to a more frustrating experience.   If it makes you feel any better, I also do not like that getValue() returns null for an empty field (and for a non-existent field.)   While I cannot say why it is this way, it has been this way for a long time.   I can tell you what I typically do, although it is more code.



I either OR the getValue call with an empty string like:


var x = gr.getValue('something') || '';


Or, I use a custom getValueAK function that also supports dot-walking.   I usually include this function in the script itself, or I dump this into a Script Include:


// You can put this in a Script Include
// Features:
// - always returns a string
// - can dot-walk
// - returns empty string instead of null (for both empty fields and non-existent fields)
// - returns string 'true' or string 'false' for boolean fields
function getValueAK(field, ge) {

      // Local vars
      var fields;

      // If you don't pass in anything, you get an empty string
      if (!field) {
              return '';
      }

      // If no second parameter, assume this
      if (!ge) {
              ge = this;
      }

      // Split fields on dot
      fields = field.split('.');

      // If there is only one field
      if (fields.length === 1) {

              // If the field exists, return a string, else return empty string
              return ge[field] !== undefined ? String(ge[field]) : '';

      } else {

              // If there is more than one field, recurse
              return this.getValueAK(fields.slice(1).join("."), ge[fields.slice(0, 1)]);
      }

}

And you can use it like this:


var gr = new GlideRecord('incident');
gr.getValueAK = getValueAK;
gr.get('d71f7935c0a8016700802b64c67c11c6');
gs.print(gr.getValueAK('caller_id.manager.name'));

I hope this helps!


Good solution,



I would make this script easier to get rid of recursion... something like this:



function getValueAK(name, gr) {


  var names = name.split('.');



  var obj = gr;



  for (var i = 0; i < names.length; i++) {


      var field = names[i];


      obj = obj[field];


      if (gs.nil(obj)) {


          obj = null;


          break;


      }


  }


  return obj ? obj.toString() : '';


}



Regards,


Andrii