1

I am not a rookie programmer I know how to console.log(myObject). What I want is to be able to print ANY object to a string with max depth, and not have empty properties in it. There are so many times when I need to print out an object to the console or to a log somewhere, and it prints the WHOLE object. That could take up so much space my terminal cant fit the whole object. The reason I am asking this here is so that someone can identify all of the edge cases that I am probably missing or places I am overthinking things.

Here is an example:

[
  {
    a: 'a',
    b: '',
    c: {
      d: 'd',
      e: {
        f: {
          g: 'g'
        }
      },
      h: [
        'i',
        'j',
        { k: 'k' }
      ],
      l: [],
    }
  }
]

printAny(myObject,5) should output:

[
  {
    a: 'a',
    c: {
      d: 'd',
      e: {
        f: '<objec>'
      },
      h: [
        'i',
        'j',
        '<object>'
      ],
    }
  }
]

I made a jsbin to some more examples: https://jsbin.com/buzugipole/edit?js,console

It should also handle cycles. I am not opposed to using npm libraries, that is what I am using right now, but it is a hodgepodge of 3 different libraries that are all trying to solve this.

Samuel Thompson
  • 2,429
  • 4
  • 24
  • 34
  • How about [this](https://stackoverflow.com/a/10729284/965834)? (Not voting as dupe as not sure this exactly fits your requirements.) – Jeto Jan 08 '19 at 22:53
  • can you use util on the browser? Edit: util.inspect does pretty much everything i need, but it does not work on the browser – Samuel Thompson Jan 08 '19 at 23:01
  • I guess http://browserify.org/ allows you to use npm packages on your browser, but I'm unfamiliar with that so I'll let you look into it. – Jeto Jan 08 '19 at 23:05
  • If you like `util.inspect`, then you might like -> https://github.com/Automattic/util-inspect – Keith Jan 08 '19 at 23:40
  • the problem i have found with inspect is it returns a non-JSON object string. which means my logger cant interpret it. I am looking how to turn that into a nice object. I think i might just go with the regex option, and handle circular objects and empty objects on my own. – Samuel Thompson Jan 09 '19 at 18:46

1 Answers1

1

You can clone the object by recursively iterating through it's keys and values, passing along a nestingToGo number that determines how much more nesting is permitted before <object> is printed instead of the actual object:

const obj = [
  {
    a: 'a',
    b: '',
    c: {
      d: 'd',
      e: {
        f: {
          g: 'g'
        }
      },
      h: [
        'i',
        'j',
        { k: 'k' }
      ],
      l: [],
    }
  }
];

function replaceNested(obj, nestingToGo) {
  const initial = Array.isArray(obj) ? [] : {};
  return Object.entries(obj).reduce(( a, [key, val]) => {
    if (typeof val === 'object') {
      a[key] = nestingToGo === 0
      ? '<object>'
      : replaceNested(val, nestingToGo - 1)
    } else {
      a[key] = val;
    }
    return a;
  }, initial);
}

function printAny(obj, maxNesting) {
  const slimmerObj = replaceNested(obj, maxNesting);
  console.log(JSON.stringify(slimmerObj, null, 2));
}
printAny(obj, 3);

Another option would be to use a regular expression to replace all lines that start with enough spaces:

const obj = [
  {
    a: 'a',
    b: '',
    c: {
      d: 'd',
      e: {
        f: {
          g: 'g'
        }
      },
      h: [
        'i',
        'j',
        { k: 'k' }
      ],
      l: [],
    }
  }
];

function printAny(obj, maxNesting) {
  const stringified = JSON.stringify(obj, null, 2);
  const maxSpaces = maxNesting * 2;
  const pattern = new RegExp(
    String.raw`[{\[]\n {${maxSpaces + 2}}\S[\s\S]+?^ {${maxSpaces}}\S`,
    'gm'
  );
  const slimStringified = stringified.replace(pattern, '<object>');
  console.log(slimStringified);
}
printAny(obj, 4);

Errors can't really be serialized well, but if you had to, you could give Error.prototype a custom toJSON method:

const obj = [
  {
    err: new Error('foo'),
    a: 'a',
    b: '',
    c: {
      d: 'd',
      e: {
        f: {
          g: 'g'
        }
      },
      h: [
        'i',
        'j',
        { k: 'k' }
      ],
      l: [],
    }
  }
];

Error.prototype.toJSON = function() {
  return '<Error> ' + this.message;
};
function printAny(obj, maxNesting) {
  const stringified = JSON.stringify(obj, null, 2);
  const maxSpaces = maxNesting * 2;
  const pattern = new RegExp(
    String.raw`[{\[]\n {${maxSpaces + 2}}\S[\s\S]+?^ {${maxSpaces}}\S`,
    'gm'
  );
  const slimStringified = stringified.replace(pattern, '<object>');
  console.log(slimStringified);
}
printAny(obj, 4);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320