Can someone Explain why JSON returns empty unless I use " + ' ' "?

Hasnaat Khan
Tera Contributor

Hey guys so I've created an object as a script include and sent it to my client script as a JSON object to read and use the values.

        while (gr.next()) { //find viewed record data based on sys_id passed in from client
            obj.address_line_1 = gr.address_line_1 + ''; //JSON stringify returns empty unless quotations used at end
            obj.address_line_2 = gr.address_line_2 + '';
            obj.county = gr.county + '';
            obj.post_code = gr.post_code + '';
            obj.city = gr.city + '';
            return JSON.stringify(obj); //convert object to json and send to client
        }
    },

So to send it back into my client script I used JSON.stringify but it would always return "{}" or empty unless I use " + ' ' "

I fiigured it out from this thread here and I was just wondering if anyone can explain why?

https://community.servicenow.com/community?id=community_question&sys_id=56725bbedbfda740afc902d5ca961997

1 ACCEPTED SOLUTION

-O-
Kilo Patron
Kilo Patron

It is because properties of GlideRecord objects that represent fields are in fact objects of "type" GlideElement. So when you write

gr.address_line_1

address_line_1 is an object of type GlideElement. But it is not a genuine JavaScript object, it does not look to the run-time as if it had any enumerable properties, so it is serialized (stringified) as if it were an empty object. There are two ways a GlideElement "gives up" its underlying loaded value: by calling its toString() method, or - in global scope - by calling its getValue() method (not to be confused with its parent GlideRecord's getValue() method).

So when you write

obj.address_line_1 = gr.address_line_1;

you are attributing an (GlideElement) object reference to obj.address_line_1 which JSON.stringify() cannot inspect and so cannot serialize (stringify), whereas when you write

obj.address_line_1 = gr.address_line_1 + '';

which is the same as

obj.address_line_1 = gr.address_line_1.toString();

you are attributing a primitive string value to obj.address_line_1 which JSON.stringify() is for sure able to inspect and serialize.

Whenever you see gr.<a field name> used and it works, it is because it is used in a place where a string is expected and thus gr.<a field name>.toString() is automatically called by the run-time and thus the underlying value is "extracted" and used. That is why for instance gs.debug(gr.number); (assuming gr is a valid task GlideRecord) would print the number of the task in Scripts - Background: gs.debug() internally at some point, when it tries to print the debug message, it expects a string. If the message passed in as 1st parameter is not a string, it will first convert it to a string, by calling the passed in value's toString() method and thus getting the underlying value. In the end it is as if one wrote gs.debug(gr.number.toString()).

View solution in original post

5 REPLIES 5

Aman Kumar S
Kilo Patron

by using + "", you are essentially converting an object to string, you can also use toString() function

for eg:

 obj.address_line_2 = gr.address_line_2.toString();

Best Regards
Aman Kumar

Thank you for this answer! 

-O-
Kilo Patron
Kilo Patron

It is because properties of GlideRecord objects that represent fields are in fact objects of "type" GlideElement. So when you write

gr.address_line_1

address_line_1 is an object of type GlideElement. But it is not a genuine JavaScript object, it does not look to the run-time as if it had any enumerable properties, so it is serialized (stringified) as if it were an empty object. There are two ways a GlideElement "gives up" its underlying loaded value: by calling its toString() method, or - in global scope - by calling its getValue() method (not to be confused with its parent GlideRecord's getValue() method).

So when you write

obj.address_line_1 = gr.address_line_1;

you are attributing an (GlideElement) object reference to obj.address_line_1 which JSON.stringify() cannot inspect and so cannot serialize (stringify), whereas when you write

obj.address_line_1 = gr.address_line_1 + '';

which is the same as

obj.address_line_1 = gr.address_line_1.toString();

you are attributing a primitive string value to obj.address_line_1 which JSON.stringify() is for sure able to inspect and serialize.

Whenever you see gr.<a field name> used and it works, it is because it is used in a place where a string is expected and thus gr.<a field name>.toString() is automatically called by the run-time and thus the underlying value is "extracted" and used. That is why for instance gs.debug(gr.number); (assuming gr is a valid task GlideRecord) would print the number of the task in Scripts - Background: gs.debug() internally at some point, when it tries to print the debug message, it expects a string. If the message passed in as 1st parameter is not a string, it will first convert it to a string, by calling the passed in value's toString() method and thus getting the underlying value. In the end it is as if one wrote gs.debug(gr.number.toString()).

Hasnaat Khan
Tera Contributor

Thank you for this in depth answer! Very informative