π§ JSON.stringify vs JSON.parse β Deep Dive
In JavaScript, these two APIs convert between JavaScript values and JSON text:
JSON.stringify(value) β JS value β JSON string
JSON.parse(text) β JSON string β JS value
Think:
stringify = serialize (object β text)
parse = deserialize (text β object)
βοΈ 1) JSON.stringify β How it works internally
π― Basic
const obj = { name: "Ashish", age: 25 };
const str = JSON.stringify(obj);
// '{"name":"Ashish","age":25}'
π¬ Internal Steps (conceptual)
Input JS value
β
Walk the structure (recursive)
β
Convert primitives to JSON tokens
β
Build a valid JSON string
Objects β { "key": value }
Arrays β [ ... ]
Strings β quoted with escaping
Numbers/booleans β as-is
π§© Examples (important cases)
β
Nested objects
JSON.stringify({ a: 1, b: { c: 2 } });
// '{"a":1,"b":{"c":2}}'
β οΈ undefined, functions, symbols
JSON.stringify({
a: undefined,
b: function () {},
c: Symbol("x"),
d: 1
});
// '{"d":1}'
π These are omitted in objects
β οΈ In arrays
JSON.stringify([1, undefined, function(){}, 3]);
// '[1,null,null,3]'
π They become null in arrays
β οΈ Dates
JSON.stringify({ d: new Date("2024-01-01") });
// '{"d":"2024-01-01T00:00:00.000Z"}'
π Uses toJSON() β ISO string
β Circular references
const a = {};
a.self = a;
JSON.stringify(a); // β TypeError
π§ Advanced: replacer & space
Replacer (filter/transform)
JSON.stringify({ a: 1, b: 2 }, ["a"]);
// '{"a":1}'
or function:
JSON.stringify({ a: 1, b: 2 }, (key, value) =>
key === "b" ? undefined : value
);
// '{"a":1}'
Pretty print
JSON.stringify(obj, null, 2);
βοΈ 2) JSON.parse β How it works internally
π― Basic
const str = '{"name":"Ashish","age":25}';
const obj = JSON.parse(str);
// { name: "Ashish", age: 25 }
π¬ Internal Steps
Input JSON string
β
Lexer + Parser (strict JSON grammar)
β
Build JS objects/arrays/primitives
π JSON must be valid:
Double quotes required
No trailing commas
π§© Examples
β
Array
JSON.parse('[1, 2, 3]');
// [1, 2, 3]
β Invalid JSON
JSON.parse("{ name: 'Ashish' }"); // β Error
π Must be:
JSON.parse('{ "name": "Ashish" }');
π§ Advanced: reviver
Transform values during parsing:
const obj = JSON.parse('{"date":"2024-01-01"}', (key, value) => {
if (key === "date") return new Date(value);
return value;
});
π Convert string β Date object
π Round Trip Example
const original = { x: 1, y: [2, 3] };
const str = JSON.stringify(original);
const copy = JSON.parse(str);
console.log(copy); // deep copy-like
β οΈ Important Limitations
β Loses functions
JSON.stringify({ fn: () => {} });
// '{}'
β Loses undefined
JSON.stringify({ a: undefined });
// '{}'
β Loses class/prototype
class User {
constructor(name) {
this.name = name;
}
}
const u = new User("A");
const copy = JSON.parse(JSON.stringify(u));
copy instanceof User; // false β
βοΈ stringify vs parse
Feature stringify parse
Direction JS β JSON string JSON string β JS
Output string object/array
Errors circular refs invalid JSON
Customization replacer reviver
π§ Real-World Use Cases
π¦ API communication
fetch("/api", {
method: "POST",
body: JSON.stringify(data)
});
πΎ Local storage
localStorage.setItem("user", JSON.stringify(user));
const user = JSON.parse(localStorage.getItem("user"));
π Deep clone (limited)
const clone = JSON.parse(JSON.stringify(obj));
π Works only for simple data
π§ Mental Model
stringify β βconvert JS to transportable textβ
parse β βrebuild JS from textβ
π― Final Takeaways
JSON.stringify serializes JS β JSON string
JSON.parse deserializes JSON β JS object
They are inverse operations
But not perfect (data loss for functions, prototypes, etc.)