2

For example I have following code:

var obj = {
    name: "alex",
    lastname: "aaa",
    portfolio: {
        stocks: "TSLA, BA"
    },
    comments: "some\nrandom\ndescription"
};

console.log("JSON OUT:\n" + obj.comments);

console.log("STRING OUT:\n" + JSON.stringify(obj, null, 2));

Which results in:

JSON OUT:
some
random
description
STRING OUT:
{
  "name": "alex",
  "lastname": "aaa",
  "portfolio": {
    "stocks": "TSLA, BA"
  },
  "comments": "some\nrandom\ndescription"
}

As you can see it escapes '\n' characters in comments value. In other words, it replaces '\n' with '\\n' in resulting string. Is there any possibility how I could avoid this behavior? I tried using replace function in stringify() 2nd parameter which does something like that return v.replace(/\\n/g, "\n"); but it newer worked (probably because original string contains just \n and final string gets screwed up after replace function finishes).

There is also another solution with involves .replace(/\\n/g, "\n") on final string, but it screw up all blank spaces which stringify() function adds:

{
  "name": "alex",
  "lastname": "aaa",
  "portfolio": {
    "stocks": "TSLA, BA"
  },
  "comments": "some
random
description"
}

But I want well-formatted human-readable string in output after JSON.stringify() call and I don't need to convert it back to JSON later:

{
  "name": "alex",
  "lastname": "aaa",
  "portfolio": {
    "stocks": "TSLA, BA"
  },
  "comments": "some
  random
  description"
}
Andrey
  • 35
  • 4
  • 2
    The name of the `json` variable is wrong. It's content is an object and not JSON -> [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – Andreas Jan 03 '22 at 13:52
  • 2
    What do you want to achieve with this? [This might be a XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Andreas Jan 03 '22 at 13:53
  • @Andreas, I updated question with desired output – Andrey Jan 03 '22 at 13:57
  • 1
    _"desired output"_ does not explain why you want it that way? Valid JSON has no white-space other than spaces in it. – Andreas Jan 03 '22 at 14:00
  • 1
    You won't be able to `JSON.parse` it, if it is not escaped. For instance `JSON.parse('{"foo": "\n"}')` does not work, while `JSON.parse('{"foo": "\\n"}')` does work correctly. It seems that your desired output is not in JSON format – A_A Jan 03 '22 at 14:00
  • *"As you can see it escapes '\n' characters in comments value. In other words, it replaces '\n' with '\\n' in resulting string."*: no, I don't see that -- there is no `\\n` in the output. – trincot Jan 03 '22 at 14:03
  • @A_A I use JSON.stringify() to get a human-readable string which won't be parsed back to JSON... – Andrey Jan 03 '22 at 14:05
  • I think you are confused about what `"....\n...."` represents. There is no literal `\n`. That represents a single newline character, and it is how it **should** be represented in JSON. If you want something else than JSON, then don't tag this with `json`, and specify the rules for the non-JSON output you want. – trincot Jan 03 '22 at 14:07
  • @trincot well, you don't actually see \n character in the output because it parsed as a new line, so you see the new line instead. When I say \\n it appears as \n in the output. Try calling replace function from my description if you don't agree – Andrey Jan 03 '22 at 14:09
  • 1
    You are confusing JSON with some custom format you want. Even JavaScript does not allow a double-quoted string literal to be spanning multiple lines without adding backslash line terminators. See [how do I break a string across multiple lines](https://stackoverflow.com/questions/508269/how-do-i-break-a-string-across-more-than-one-line-of-code-in-javascript). – trincot Jan 03 '22 at 14:10
  • @trincot thanks for the explanation. I understand that there is no way how to get well-formatted output with JSON.stringify. But are there other solutions how I could convert object into human-readable string? – Andrey Jan 03 '22 at 14:17
  • Write either a custom `toString` method on your objects/classes or write a function that takes an object with that shape as input and outputs what you want. – Jared Smith Jan 03 '22 at 14:19
  • *"well-formatted output with JSON.stringify"*: that is ambiguous. `JSON.stringify` produces JSON. It can be well formatted with the second and third argument to that function. But what you want is to format it in a way that **destroys** the JSON format. That is no longer JSON. Since your question is not about generating JSON, please rephrase your question and remove the `json` tag. – trincot Jan 03 '22 at 14:19
  • 1
    @JaredSmith custom toString sounds good to me. Thank you! – Andrey Jan 03 '22 at 14:27

1 Answers1

3

You could improve your replace-logic, and capture the original indent. Then reinsert that indent when replacing the individual \n:

var obj = {
    name: "alex",
    lastname: "aaa",
    portfolio: {
        stocks: "TSLA, BA"
    },
    comments: "some\nrandom\ndescription"
};

let result = JSON.stringify(obj, null, 2).replace(/^(\s*).*\\n.*$/gm, (line, indent) =>
    line.replace(/\\n/g, "\n" + indent)
);
console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286