user3550203
user3550203

Reputation: 729

Space in between JSON.stringify output

I am using Jquery to get all products name from page and than put it on array. I am using this code

 <script type="text/javascript">
 jQuery(document).ready(function($) {
    var products = $(".product-name").map(function() {
    return { name: $(this).text() }
 }) .get();
 console.log(JSON.stringify(products));
 });
 </script>

This give me output in this format

[{"name":"Sample Product Name"},{"name":"Sample Product Name 2"}]

What I am trying to achieve is to have one space in between these two objects after "," so the output will look something like this

[{"name":"Sample Product Name"}, {"name":"Sample Product Name 2"}]

Any advise? I am struggling from hours and no success.

Here is the jsfiddle http://jsfiddle.net/2MeMY/1/

Upvotes: 28

Views: 34779

Answers (4)

Lionel Rowe
Lionel Rowe

Reputation: 5963

All of the existing answers for how to format JSON on a single line are buggy:

const obj = { x: '{ [ ] },{' }
// https://stackoverflow.com/a/24834852
const v1 = JSON.stringify(obj).split('},{').join('}, {')
// https://stackoverflow.com/a/57467694
const v2 = Stringify_WithSpaces(obj)
// https://stackoverflow.com/a/54434746
const v3 = JSON.stringify(obj).replace(/},{/g,'}, {')

console.log(obj.x)            // '{ [ ] },{'
console.log(JSON.parse(v1).x) // '{ [ ] }, {'
console.log(JSON.parse(v2).x) // '{[]},{'
console.log(JSON.parse(v3).x) // '{ [ ] }, {'

What you need to do is initially pad with a character that can never appear within a raw JSON string (e.g. a raw tab), then make sure each replacement regex only matches when such characters (tabs, newlines) are present.

function stringify(obj, options) {
    const { padBraces, padBrackets } = { padBraces: true, padBrackets: false, ...options }

    const braces = padBraces ? ['{ ', ' }'] : ['{', '}']
    const brackets = padBrackets ? ['[ ', ' ]'] : ['[', ']']

    return JSON.stringify(obj, null, '\t')
        .replaceAll(/\{[\t\n]+/g, braces[0])
        .replaceAll(/[\t\n]+\}/g, braces[1])
        .replaceAll(/\[[\t\n]+/g, brackets[0])
        .replaceAll(/[\t\n]+\]/g, brackets[1])
        .replaceAll(/[\t\n]+/g, ' ')
}

const obj = { a: [{ x: '{ [ ] },{', b: { y: 6 } }] }

console.log('normal:', stringify(obj))
console.log('narrow:', stringify(obj, { padBraces: false }))
console.log('wide:  ', stringify(obj, { padBrackets: true }))

Upvotes: 0

Venryx
Venryx

Reputation: 18077

If you want a json-output that is:

  1. Single-line
  2. Has spaces between prop-names and prop-values (and between items)
  3. Has spaces between each comma and the next prop-name/item

You can use this:

function Stringify_WithSpaces(obj) {
	let result = JSON.stringify(obj, null, 1); // stringify, with line-breaks and indents
	result = result.replace(/^ +/gm, " "); // remove all but the first space for each line
	result = result.replace(/\n/g, ""); // remove line-breaks
	result = result.replace(/{ /g, "{").replace(/ }/g, "}"); // remove spaces between object-braces and first/last props
	result = result.replace(/\[ /g, "[").replace(/ \]/g, "]"); // remove spaces between array-brackets and first/last items
	return result;
}

let obj = [{name: "Sample Product Name"}, {name: "Sample Product Name 2"}];
console.log("Stringified with spaces: " + Stringify_WithSpaces(obj));

And here's the function as a one-line expression:

JSON.stringify(obj, null, 1).replace(/^ +/gm, " ").replace(/\n/g, "").replace(/{ /g, "{").replace(/ }/g, "}").replace(/\[ /g, "[").replace(/ \]/g, "]")

Extended Typescript version


Here's a more verbose version (in Typescript) with options:

export class ToJSON_WithSpaces_Options {
    insideObjectBraces = false;
    insideArrayBrackets = false;
    betweenPropsOrItems = true;
    betweenPropNameAndValue = true;
}
export function ToJSON_WithSpaces(obj, options?: Partial<ToJSON_WithSpaces_Options>) {
    options = Object.assign({}, new ToJSON_WithSpaces_Options(), options);

    let result = JSON.stringify(obj, null, 1); // stringify, with line-breaks and indents
    result = result.replace(/^ +/gm, " "); // remove all but the first space for each line
    result = result.replace(/\n/g, ""); // remove line-breaks
    if (!options.insideObjectBraces) result = result.replace(/{ /g, "{").replace(/ }/g, "}");
    if (!options.insideArrayBrackets) result = result.replace(/\[ /g, "[").replace(/ \]/g, "]");
    if (!options.betweenPropsOrItems) result = result.replace(/, /g, ",");
    if (!options.betweenPropNameAndValue) result = result.replace(/": /g, `":`);
    return result;
}

Ideally, this sort of function will apply the regular-expressions prior to removing the line-breaks (so that it can guarantee it's not modifying text within user-supplied strings), but I'll leave that for someone else to do since the above is sufficient for my use-case (and I think most others).

Upvotes: 3

Pratik Rathod
Pratik Rathod

Reputation: 41

You can also do like this with replace

console.log(JSON.stringify(products).replace(/},{/g,'}, {')); 

// /},{/g means all occurance of },{

Upvotes: 0

dave
dave

Reputation: 64725

This may not be what you want, but if you just want it to look better, I would recommend:

console.log(JSON.stringify(products, null, 2));

which would give you

[
  {
    "name": "Sample Product Name"
  },
  {
    "name": "Sample Product Name 2"
  }
]

In the console. If you really just want a space before commas, you could do:

console.log(JSON.stringify(products).split('},{').join('}, {'));

http://jsfiddle.net/2MeMY/3/

Upvotes: 41

Related Questions