I often want to "pretty print" (include extra white-space to make it easier for humans to interpret) JavaScript objects, and JSON.stringify(myObject, null, " ") usually suffices for this. However, in many cases, there are arrays of numbers that I really don't want split onto new lines.
Is there a simple/elegant way of accomplishing this with the native JSON.stringify function?
I tried using a "replacer" function but this seems to only facilitate alteration (e.g. modify data), filtering (e.g. omit data), and side-effects (e.g. log data) -- see also How Do I Use The Replacer Function With JSON Stringify?.
Alternatively, is there an established module/library/utility for doing this already or should I write my own?
There appear to be many search results on npm.org for "stringify", but the ones I saw seem to just be variations that either run more efficiently on a particular problem domain or avoid problems related to circular/cyclic data structures.
const obj = {
foo: "bar",
oneLine: [1,2,3],
multipleLines: [{
name: "X",
alsoOneLine: [4,5,6]
}, {
name: "Y"
}]
};
document.write(`
<pre>
// This isn't the output I want.
// The arrays containing only numbers should have their elements
// all printed on the same line.
${JSON.stringify(obj, null, " ")}
</pre>
`);
You can use a regular expression to search the stringified version for arrays of numbers, and replace the whitespaces in all those those arrays-of-numbers with the empty string. By anchoring the beginning of the pattern to the beginning of a line with ^, you can ensure that the matched key-value pair (or plain value, in the case the array of numbers is contained in another array) is an array, and not something else, like a string that contains something that looks like a JSON-array-of-numbers:
const obj = {
foo: "bar",
oneLine: [1, 2, 3],
multipleLines: [{
name: "X",
alsoOneLine: [4, 5, 6],
inner: [
[1, 2, 3],
[4, 5, 6]
]
}, {
name: "Y"
}]
};
const stringified = JSON.stringify(obj, null, " ");
const numArraysOnOneLine = stringified.replace(
/^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])/gm,
(_, leadingWhitespace, possibleKeyStr='', arrStr) => (
leadingWhitespace + possibleKeyStr + arrStr.replace(/\s+/g, ''
))
);
document.write(`<pre>${numArraysOnOneLine}</pre>`);
https://regex101.com/r/XfuqoT/1
The pattern
^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])
means:
^ - Match the start of a line( *) First capturing group: capture the leading whitespace("[^"]+": )? Second group, optional: match the double-quoted key, if the array is contained in an object\[ - Beginning of the third group. Match a literal [(?:\s+\d+,)* - Repeat a group of whitespace characters followed by digits zero or more times\s+\d+\s+ - Match the final item in the array (has no trailing comma): whitespace, followed by a digit, followed by more whitespace\] - followed by the terminating ] (end of the third group)If the numbers may contain decimals as well, then replace \d+ with \d+(?:\.\d+)? to allow for optional decimal digits.
If the object properties may contain double-quotes as well (escaped by backslash when stringified), then replace [^"]+ with (?:[^"]|\\")+ https://regex101.com/r/XfuqoT/2
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