Is there a way to log the contents of an object using Logger.log in Google App Scripts?
If I have Logger.log(data)
, the log is 'DataTableBuilder', or 'object' or something similar and incredibly unhelpful.
I want to see JSON strings of these objects if possible...
As of Nov 2013, you can use JSON.stringify()
to convert Objects
into String
s. Some Google documentation can be found here, while the full JavaScript method documentation is available on your preferred API reference, such as MDN.
Example usage:
Logger.log(JSON.stringify(obj, null, 2));
Alternately, via Stackdriver Logging (as of 2017 June):
console.log({message: "Interactive object serialization", theObject: obj})
// or
console.log(JSON.stringify(obj));
This a function I modified from another SO answer:
var Log = {
// Thanks to Amos Batto - https://stackoverflow.com/questions/603987/what-is-the-javascript-equivalent-of-var-dump-or-print-r-in-php
/*
dump() displays the contents of a variable like var_dump() does in PHP. dump() is
better than typeof, because it can distinguish between array, null and object.
Parameters:
v: The variable
howDisplay: "none", "body", "alert" (default)
recursionLevel: Number of times the function has recursed when entering nested
objects or arrays. Each level of recursion adds extra space to the
output to indicate level. Set to 0 by default.
Return Value:
A string of the variable's contents
Limitations:
Can't pass an undefined variable to dump().
dump() can't distinguish between int and float.
dump() can't tell the original variable type of a member variable of an object.
These limitations can't be fixed because these are *features* of JS. However, dump()
*/
dump: function(functionName, v, recursionLevel) {
recursionLevel = (typeof recursionLevel !== 'number') ? 0 : recursionLevel;
var vType = typeof v;
var out = vType;
switch (vType) {
case "number":
/* there is absolutely no way in JS to distinguish 2 from 2.0
so 'number' is the best that you can do. The following doesn't work:
var er = /^[0-9]+$/;
if (!isNaN(v) && v % 1 === 0 && er.test(3.0))
out = 'int';*/
case "boolean":
out += ": " + v;
break;
case "string":
out += "(" + v.length + '): "' + v + '"';
break;
case "object":
//check if null
if (v === null) {
out = "null";
}
//If using jQuery: if ($.isArray(v))
//If using IE: if (isArray(v))
//this should work for all browsers according to the ECMAScript standard:
else if (Object.prototype.toString.call(v) === '[object Array]') {
out = 'array(' + v.length + '): {\n';
for (var i = 0; i < v.length; i++) {
out += repeatString(' ', recursionLevel) + " [" + i + "]: " +
Log.dump(functionName, v[i], recursionLevel + 1) + "\n";
}
out += repeatString(' ', recursionLevel) + "}";
}
else { //if object
sContents = "{\n";
cnt = 0;
for (var member in v) {
//No way to know the original data type of member, since JS
//always converts it to a string and no other way to parse objects.
sContents += repeatString(' ', recursionLevel) + " " + member +
": " + Log.dump(functionName, v[member], recursionLevel + 1) + "\n";
cnt++;
}
sContents += repeatString(' ', recursionLevel) + "}";
out += "(" + cnt + "): " + sContents;
}
break;
}
Logger.log(functionName + ' - ' + out);
return;
// Private Functions
// -----------------
/* repeatString() returns a string which has been repeated a set number of times */
function repeatString(str, num) {
out = '';
for (var i = 0; i < num; i++) {
out += str;
}
return out;
} // Log.dump.repeatString()
}, // Log.dump()
}
I keep coming to this thread looking for a neat way to log nested objects and arrays in GAS. I needed an output like this:
{
food : {
pizza : [
crust,
sauce,
topping,
cheese
]
},
drink : {
bananaShake : [
banana,
milk,
sugar
]
}
}
UPDATE: This is a more elegant solution: Logger.log(JSON.stringify(obj, null, 2))
. Thanks to @Zach's comment below.
In any case this is the function I was using earlier:
//-------------------------------------------------------------------------------
// Display the passed object in the Logger
// @param {object} obj - object to be logged
// @param {string} log - (for internal use only) final output sent to the logger
// @param {number} count - (for internal user only) keeps track of the number of
// iteration that the program is running in.
//-------------------------------------------------------------------------------
function logObj(obj, log, count) {
var def = {};
// Set default values to the passed arguments
obj = obj == undefined? def : obj;
log = log == undefined? '\n' : log;
count = count == undefined? 1 : count;
// If it's date object convert it to string
if(obj instanceof Date) {
obj = obj.toString();
}
// If it's a function represent it as a string
if(typeof obj == 'function') {
obj = 'function() {}';
}
// If it's an Object
if(typeof obj == 'object') {
var isArray = obj.constructor.name == 'Array';
var length = 0;
for(var i in obj) {
length++;
}
if(isArray) log += '[';
else log += '{';
if(length) {
log += '\n';
var num = 1;
for(var i in obj) {
// add tabs based on which iteration the program is running in
var tab1 = '';
var tab2 = ''; // this is one tab less than tab1
for(var k = 0; k < count; k++) {
tab1 += '\t';
if(k < (count - 1)) {
tab2 += '\t';
}
}
log += tab1;
if(!isArray) log += i + ' : ';
log += logObj(obj[i], '', count + 1);
if(num < length) {
log += ',\n';
}
num++;
}
log += '\n' + tab2;
}
if(isArray) log += ']';
else log += '}';
// if it's not the first iteration, return the log instead of printing it
if(count > 1) {
return log;
}
}
else if(count > 1) {
return obj;
}
else {
log = obj;
}
if(count == 1) {
Logger.log(log);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With