loading...

Discussion on: Forgiving pretty-print

Collapse
eruizdechavez profile image
Erick Ruiz de Chavez

There are many tools you can use to format a JSON string, the most common way is to JSON.parse and then JSON.stringify it. You could also try something like jq in the terminal.

const myJsonString = " ... ";
try {
  console.log(JSON.stringify(JSON.parse(myJsonString), null, 2));
  // or, if in the browser, you can use copy() instead of console.log to get the value into the clipboard.
} catch (e) {
  console.error(e);
}

In case you didn't know, JSON.stringify can be used to "pretty print" a JS object right in the browser (or node, deno, etc.) without any extra dependencies.

developer.mozilla.org/en-US/docs/W...

Collapse
patarapolw profile image
Pacharapol Withayasakpunt Author

My challenge is JSON is malformed, but pretty-printing should still works. (probably to a limited extent)

Collapse
eruizdechavez profile image
Erick Ruiz de Chavez

Here is a very basic formatter that will try to do some basic formatting to the JSON string. You can change the value of indentWith to any other string you want, I used -- to make it more obvious when testing it. The value of myJsonString is missing a " in a key, therefore it is a broken JSON.

const myJsonString = ` { "Account": { "Account Name": "Firefly", "Order": [ { "OrderID: "order103", "Product": [ { "Product Name": "Bowler Hat", "ProductID": 858383, "SKU": "0406654608", "Description": { "Colour": "Purple", "Width": 300, "Height": 200, "Depth": 210, "Weight": 0.75 }, "Price": 34.45, "Quantity": 2 }, { "Product Name": "Trilby hat", "ProductID": 858236, "SKU": "0406634348", "Description": { "Colour": "Orange", "Width": 300, "Height": 200, "Depth": 210, "Weight": 0.6 }, "Price": 21.67, "Quantity": 1 } ] }, { "OrderID": "order104", "Product": [ { "Product Name": "Bowler Hat", "ProductID": 858383, "SKU": "040657863", "Description": { "Colour": "Purple", "Width": 300, "Height": 200, "Depth": 210, "Weight": 0.75 }, "Price": 34.45, "Quantity": 4 }, { "ProductID": 345664, "SKU": "0406654603", "Product Name": "Cloak", "Description": { "Colour": "Black", "Width": 30, "Height": 20, "Depth": 210, "Weight": 2 }, "Price": 107.99, "Quantity": 1 } ] } ] } }`;
const indentWith = "--";

let currIndent = 0;

const prettyIsh = myJsonString.split("").reduce((result, char) => {
  result += char;

  if (char === "{" || char === "[") {
    currIndent++;
    result += "\n" + indentWith.repeat(currIndent);
  } else if (char === ",") {
    result += "\n" + indentWith.repeat(currIndent);
  } else if (char === "}" || char === "]") {
    currIndent--;
    result += "\n" + indentWith.repeat(currIndent);
  }

  return result;
}, "");

console.log(prettyIsh);

This will output the following string when run with node in the terminal:

{
-- "Account": {
---- "Account Name": "Firefly",
---- "Order": [
------ {
-------- "OrderID: "order103",
-------- "Product": [
---------- {
------------ "Product Name": "Bowler Hat",
------------ "ProductID": 858383,
------------ "SKU": "0406654608",
------------ "Description": {
-------------- "Colour": "Purple",
-------------- "Width": 300,
-------------- "Height": 200,
-------------- "Depth": 210,
-------------- "Weight": 0.75 }
------------,
------------ "Price": 34.45,
------------ "Quantity": 2 }
----------,
---------- {
------------ "Product Name": "Trilby hat",
------------ "ProductID": 858236,
------------ "SKU": "0406634348",
------------ "Description": {
-------------- "Colour": "Orange",
-------------- "Width": 300,
-------------- "Height": 200,
-------------- "Depth": 210,
-------------- "Weight": 0.6 }
------------,
------------ "Price": 21.67,
------------ "Quantity": 1 }
---------- ]
-------- }
------,
------ {
-------- "OrderID": "order104",
-------- "Product": [
---------- {
------------ "Product Name": "Bowler Hat",
------------ "ProductID": 858383,
------------ "SKU": "040657863",
------------ "Description": {
-------------- "Colour": "Purple",
-------------- "Width": 300,
-------------- "Height": 200,
-------------- "Depth": 210,
-------------- "Weight": 0.75 }
------------,
------------ "Price": 34.45,
------------ "Quantity": 4 }
----------,
---------- {
------------ "ProductID": 345664,
------------ "SKU": "0406654603",
------------ "Product Name": "Cloak",
------------ "Description": {
-------------- "Colour": "Black",
-------------- "Width": 30,
-------------- "Height": 20,
-------------- "Depth": 210,
-------------- "Weight": 2 }
------------,
------------ "Price": 107.99,
------------ "Quantity": 1 }
---------- ]
-------- }
------ ]
---- }
-- }
Collapse
eruizdechavez profile image
Erick Ruiz de Chavez

That is most likely impossible. In order to pretty print some JSON value it needs to be valid. Otherwise there is no way to know if something is a key, a value, an array, a string, etc. The try/catch in my example will give you the first error it finds and then you can use that to (eventually) fix the string.

As a last resort, you could code a simple script to insert new lines (and maybe even do some indentation) whenever you see some standard characters like ", : or {.