You can use JSON.stringify()
to turn a JSON object into a string.
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj))
This results in a single line string:
{"a":1,"b":3,"c":"boo!"}
However, you can also set two optional parameters, a filtering array or callback method and an indentation parameter. Setting the indentation to four, for example, creates a multi line string with 4 spaces indentation:
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj, false, 4))
Output:
{
"a": 1,
"b": 3,
"c": "boo!"
}
If instead of spaces you want tabs, you can also defined the indentation parameter as a string:
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj, false, "\t"))
Output:
{
"a": 1,
"b": 3,
"c": "boo!"
}
Or any other string:
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj, false, "xxx"))
Output:
{
xxx"a": 1,
xxx"b": 3,
xxx"c": "boo!"
}
You can define an array of keys you want to show to filter the outcome:
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj, ['a','c'], 4))
Output:
{
"a": 1,
"c": "boo!"
}
And you can write a filtering callback function that gets applied to the JSON object. For example, to only allow for numbers to show:
const onlyNumbers = (key,value) => {
return (typeof value === 'string') ? undefined : value
}
let obj = {"a": 1, "b": 3, "c": "boo!"};
console.log(JSON.stringify(obj, onlyNumbers, 4))
Output:
{
"a": 1,
"b": 3
}
You can see more examples on MDN.
Whilst I like these options, it always feels weird to me when a method allows for different values to determine what to do. Having the replacer either be an array or a callback and the spaces option be a number or a string feels confusing. What do you think?
Top comments (2)
Nice, I learned something new today.
In your closing question you ask about our thoughts regarding the design of the API; so here are mine:
JSON.stringify()
but instead would have named itJSON.serialize()
JSON.format(input: string, options?: FormattingOptions)
that only operates on a string, not on an object. If I wanted to serialize and format an object I would need to callJSON.format(JSON.serialize(foo))
and I wouldn't roll both cases into oneserialize
andformat
. So maybe I must revise my earlier thought and allow for theformat
function to also accept objects, so it can serialize and format data in one go.format
and just use the minimal formatting which produces no linebreaks and no indentation. The output would be exactly equal to the output fromserialize
. So I could get rid ofserialize
to keep my API nice and lean. And now I've come full circle, and I should probably rename myformat
function to better convey that it can do both: formatting and serialization. What to name it? Yes, maybe we name it.stringify()
I agree; the API is so fuzzy with all the different ways the parameters get interpreted that it's hard to read a call to
stringify
and know what it's doing.Having said that, I find the replacer to be very useful:
Extending JSON for fun and profit
Klemen Slavič ・ Oct 28 '18 ・ 6 min read