1

I've read several posts on using JSON.stringify to pretty print a JSON string with Javascript. However, it seems to re-order the nodes. I would like to have a formatted JSON object in the same order as the string provided.

Here's an example of what I get using the prescribed methods

var sJson = '{"2":"stuff", "1":"care"}';
alert(JSON.stringify(JSON.parse(sJson), null, 2));

Result:

{
  "1": "care",
  "2": "stuff"
}

Desired Result:

{
  "2": "stuff",
  "1": "care"
}

I'm happy to use an external library if JSON.stringify is unable to do this. Note: I'm starting with a minified JSON string from the server.

quickshiftin
  • 66,362
  • 10
  • 68
  • 89
  • 1
    See http://stackoverflow.com/questions/24242441/does-json-stringify-preserves-order-of-objects-in-array and http://dev-answers.blogspot.com/2012/03/javascript-object-keys-being-sorted-in.html. This leads to another link: http://stackoverflow.com/questions/5773950/how-to-keep-an-javascript-object-array-ordered-while-also-maintaining-key-lookup -- this presents an interesting solution. – Jonathan Lam Oct 08 '15 at 01:30
  • If there is some expectation of order, why not try to implement a sort of some kind? – Evan Bechtol Oct 08 '15 at 01:33
  • 2
    Objects don't have order in javascript, if you want order use arrays – charlietfl Oct 08 '15 at 01:42
  • 1
    ^ Since iterating over the object does not maintain order, parsing the string to a JS object is probably not the best idea. – Felix Kling Oct 08 '15 at 01:45
  • @charlietfl: Rather use a library that can format JSON without converting it to a JS object. – Felix Kling Oct 08 '15 at 01:45
  • Yup @FelixKling, that was the way to go! – quickshiftin Oct 08 '15 at 02:37

3 Answers3

4

Because in JavaScript Objects are not ordered, properties in an Object do not preserve order. In order to keep your order you would need to change your JSON to use an array instead: [{"2":"stuff"}, {"1":"care"}].

Spencer Wieczorek
  • 21,229
  • 7
  • 44
  • 54
  • The question is about pretty-printing the JSON, which means it's for human consumption. We all know the order doesn't matter to programs, but sometimes a program might write JSON data to a file in a particular order, and that order might make sense to humans. – Laurence Renshaw Apr 01 '20 at 09:14
1

We had a similar question regarding JSON formatting for a display. A couple of robust solutions are available:

  • The 'json-order' package offers parsing, formatting & pretty-printing with stable ordering. This is based on having ordered input.
  • The 'fast-json-stable-stringify' package offers deterministic formatting based on sorting.

My quick testing with Chrome also found that JSON.parse() seemed to preserve order; this covers much of the browser market (Chrome, Edge, etc) but is not guaranteed on other browsers. This may offer a cheap partial solution, but is not fully robust.

Thomas W
  • 13,940
  • 4
  • 58
  • 76
  • For me, the original problem is still present on the latest version of chrome. Would you mind updating your answer with a sample code snippet using `json-order`, and the original string of issue (`'{"2":"stuff", "1":"care"}'`), and I'll be glad to accept this as the correct answer. – quickshiftin Feb 25 '21 at 01:17
0

I was able to port the php function I found on this page; it's working like a champ.

function pad(width, string, padding) { 
  return (width <= string.length) ? string : pad(width, padding + string, padding)
}

function json_pretty(json, html)
{
    var
        out   = '',
        nl    = "\n",
        cnt   = 0,
        tab   = 4,
        len   = json.length,
        space = ' ';

    if(html == true) {
        space = '&nbsp;';
        nl    = '<br/>';
    }

    k = space.length ? space.length : 1;

    for (i=0; i<=len; i++) {
        char = json.substring(i, i+1);
        if(char == '}' || char == ']') {
            cnt--;
            out += nl + '' + pad(tab * cnt * k, '', space);
        }
        else if(char == '{' || char == '[') {
            cnt++;
        }

        out += char;
        if(char == ',' || char == '{' || char == '[') {
            out += nl + pad(tab * cnt * k, '', space);
        }

        if(char == ':') {
            out += ' ';
        }
    }
    return out;
}
quickshiftin
  • 66,362
  • 10
  • 68
  • 89
  • This snippet doesn't to check for " double-quote to begin/ end a string value, and will break (produce erroneous output) when it encounters braces/ brackets within a string. See the JSON spec as a reference: https://www.json.org/json-en.html – Thomas W Feb 24 '21 at 23:01