JSON
Imagine you are moving and want to send a friend a wardrobe by mail. A whole wardrobe will not fit into an envelope. But you can write down on a sheet of paper which boards it is made of, and your friend will build the same wardrobe from that note.
An object in a program is in the same position. An object exists only inside a running program. To save it to a file or send it to a server, it is turned into a string. The String function does not fit this job:
const user = { name: "Ann", age: 30, admin: false };
console.log(String(user)); // [object Object]
const text = JSON.stringify(user);
console.log(text); // {"name":"Ann","age":30,"admin":false}
console.log(typeof text); // string
const copy = JSON.parse(text);
console.log(copy.name, copy.age); // Ann 30Let's go step by step:
String(user)gives a useless[object Object]: the properties are gone.JSON.stringify(user)writes all the properties into a string.typeof textconfirms that it is an ordinary string.JSON.parse(text)reads the string and builds a new objectcopyfrom it.
The JSON format
JSON (JavaScript Object Notation) is a text data format. It looks like an object written in JavaScript, but it is stricter: keys and strings go only in double quotes. Values can be objects, arrays, strings, numbers, true, false and null.
Almost every programming language understands this format, so programs exchange data through it. Two functions work with it in opposite directions:
JSON.stringifyturns a value into a JSON string;JSON.parsedoes the reverse: it reads a string and builds a new value from it, most often an object.
Reading a JSON string is called parsing. In the example copy is a different object, and copy === user gives false. Like your friend's wardrobe: the same, but not the very one.
What gets lost
This is where the wardrobe analogy stops working. You would notice that some part could not be described on the sheet. JSON.stringify drops such parts silently.
JSON has no undefined, functions, NaN or Infinity, and JSON.stringify drops or replaces them without a warning:
- a property whose value is
undefinedor a function disappears from the string entirely; NaNandInfinityare written asnull;- the
MapandSetcollections turn into the empty object{}.
const item = { id: 7, note: undefined, price: NaN, show() {} };
console.log(JSON.stringify(item)); // {"id":7,"price":null}
const tags = new Set(["js", "css"]);
console.log(JSON.stringify(tags)); // {}There is no error, and you notice the loss only when you read the data back. To save a Map, it is first turned into an array of pairs: JSON.stringify([...map]).
A copy through JSON
A JSON string has no link to the original object, and JSON.parse builds every nested object anew. That is why JSON.parse(JSON.stringify(x)) gives a deep copy: a copy in which the nested objects are new too. But it holds only what JSON can store.
The structuredClone function keeps undefined, NaN, Map and Set, but it cannot copy an object with a method:
const order = { id: 1, items: { pen: 2 }, note: undefined };
const viaJson = JSON.parse(JSON.stringify(order));
const clone = structuredClone(order);
order.items.pen = 5;
console.log(viaJson.items.pen, clone.items.pen); // 2 2
console.log("note" in viaJson, "note" in clone); // false trueLet's see what happens here:
viaJsonandcloneare two deep copies oforder.order.items.pen = 5changes a nested object of the original.- Both copies print
2: their nested objects are their own, not shared withorder. viaJsonhas nonoteproperty, whileclonekept it.
Interviewers often ask how to make a deep copy of an object. A good answer names both ways and what each of them loses.
Common mistake
The string for JSON.parse was written by the rules of JavaScript, not of JSON:
console.log("start");
const settings = JSON.parse("{ size: 'M' }"); // ✗
console.log(settings.size);SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3)Invalid text does not turn into undefined: the program stops with a SyntaxError, and the last console.log never runs. This is the error text in Node and Chrome; other browsers word it differently.
This is a runtime error despite its name SyntaxError. The program manages to print start: JSON.parse checks the text only when called, and the lines above really have run.
A key without quotes and single quotes are valid in JavaScript, but not in JSON: the correct string is '{"size":"M"}'. Because of such strict rules, JSON strings are usually not written by hand but taken from JSON.stringify.
Key points
JSON.stringifyturns a value into a JSON string, andJSON.parsebuilds a new value from a string.undefined, functions,NaN,Infinity,MapandSetare lost or replaced without an error.JSON.parse(JSON.stringify(x))gives a deep copy of only what JSON can store;structuredClonekeeps more.- An invalid string in
JSON.parsethrows aSyntaxErrorat run time.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.