Practice JS Problems

JSON.parse and JSON.stringify in JavaScript

What is JSON?

JSON (JavaScript Object Notation) — a text format for data exchange based on JavaScript syntax.

JavaScript provides two main methods for working with JSON:

  • JSON.stringify() — convert object to JSON string (serialization)
  • JSON.parse() — convert JSON string to object (deserialization)

JSON.stringify()

Converts JavaScript value to JSON string.

Basic Syntax

JSON.stringify(value, replacer, space)

Parameters

  1. value — value to convert
  2. replacer (optional) — function or array for filtering properties
  3. space (optional) — number of spaces for formatting

Simple Examples

const user = {
  name: 'John',
  age: 25,
  isActive: true
};

JSON.stringify(user);
// '{"name":"John","age":25,"isActive":true}'

// With formatting
JSON.stringify(user, null, 2);
/*
{
  "name": "John",
  "age": 25,
  "isActive": true
}
*/

What Can Be Serialized?

Supported Types

// Objects
JSON.stringify({ a: 1 });  // '{"a":1}'

// Arrays
JSON.stringify([1, 2, 3]);  // '[1,2,3]'

// Strings
JSON.stringify('text');  // '"text"'

// Numbers
JSON.stringify(42);  // '42'

// Boolean
JSON.stringify(true);  // 'true'

// null
JSON.stringify(null);  // 'null'

What Gets Ignored or Converted

const obj = {
  fn: function() {},           // Function - ignored
  undef: undefined,            // undefined - ignored
  sym: Symbol('id'),           // Symbol - ignored
  date: new Date(),            // Date → string
  nan: NaN,                    // NaN → null
  infinity: Infinity,          // Infinity → null
  regex: /test/,               // RegExp → {}
  map: new Map([[1, 'one']]),  // Map → {}
  set: new Set([1, 2, 3])      // Set → {}
};

JSON.stringify(obj);
// '{"date":"2024-01-01T00:00:00.000Z","nan":null,"infinity":null,"regex":{},"map":{},"set":{}}'

Important:

undefined, functions, and symbols:

  • In objects — ignored
  • In arrays — become null
JSON.stringify([1, undefined, function() {}, 3]);
// '[1,null,null,3]'

replacer Parameter

Array (property filtering)

const user = {
  name: 'John',
  age: 25,
  password: 'secret123',
  email: 'john@example.com'
};

// Serialize only name and email
JSON.stringify(user, ['name', 'email']);
// '{"name":"John","email":"john@example.com"}'

Function (value transformation)

const obj = {
  name: 'John',
  age: 25,
  salary: 100000
};

JSON.stringify(obj, (key, value) => {
  // Hide salary
  if (key === 'salary') return undefined;
  
  // Double age
  if (key === 'age') return value * 2;
  
  return value;
});
// '{"name":"John","age":50}'

replacer Function Parameters

  • key — property key (empty string for root object)
  • value — property value
  • this — parent object
const data = { a: 1, nested: { b: 2 } };

JSON.stringify(data, function(key, value) {
  console.log(`key: "${key}", value:`, value);
  return value;
});

// key: "", value: { a: 1, nested: { b: 2 } }  ← root object
// key: "a", value: 1
// key: "nested", value: { b: 2 }
// key: "b", value: 2

space Parameter (formatting)

const obj = { name: 'John', age: 25 };

// Number - number of spaces
JSON.stringify(obj, null, 2);
/*
{
  "name": "John",
  "age": 25
}
*/

// String - prefix for each level
JSON.stringify(obj, null, '→ ');
/*
{
→ "name": "John",
→ "age": 25
}
*/

toJSON() Method

Objects can define custom serialization behavior through toJSON() method.

const user = {
  name: 'John',
  birthDate: new Date(1998, 5, 15),
  
  toJSON() {
    return {
      name: this.name,
      age: new Date().getFullYear() - this.birthDate.getFullYear()
    };
  }
};

JSON.stringify(user);
// '{"name":"John","age":26}'

Built-in toJSON in Date

const date = new Date();
date.toJSON();  // "2024-01-15T12:00:00.000Z"

JSON.stringify({ created: date });
// '{"created":"2024-01-15T12:00:00.000Z"}'

Circular References

const obj = { name: 'John' };
obj.self = obj;  // Circular reference

try {
  JSON.stringify(obj);
} catch (error) {
  console.error(error);
  // TypeError: Converting circular structure to JSON
}

Solution: Use WeakSet

function stringifyWithoutCircular(obj) {
  const seen = new WeakSet();
  
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) {
        return '[Circular]';
      }
      seen.add(value);
    }
    return value;
  });
}

const obj = { name: 'John' };
obj.self = obj;

stringifyWithoutCircular(obj);
// '{"name":"John","self":"[Circular]"}'

JSON.parse()

Converts JSON string to JavaScript value.

Basic Syntax

JSON.parse(text, reviver)

Parameters

  1. text — JSON string to parse
  2. reviver (optional) — value transformation function

Examples

JSON.parse('{"name":"John","age":25}');
// { name: 'John', age: 25 }

JSON.parse('[1, 2, 3]');
// [1, 2, 3]

JSON.parse('true');   // true
JSON.parse('null');   // null
JSON.parse('"text"'); // "text"
JSON.parse('42');     // 42

reviver Parameter

Function for transforming values during parsing.

const json = '{"name":"John","birthDate":"1998-06-15T00:00:00.000Z"}';

const user = JSON.parse(json, (key, value) => {
  if (key === 'birthDate') {
    return new Date(value);  // Convert string to Date
  }
  return value;
});

console.log(user.birthDate instanceof Date);  // true

reviver Function Parameters

  • key — property key
  • value — property value
  • this — parent object

Function is called bottom-up (from nested to root).

const json = '{"a":1,"nested":{"b":2}}';

JSON.parse(json, (key, value) => {
  console.log(`key: "${key}", value:`, value);
  return value;
});

// key: "a", value: 1
// key: "b", value: 2
// key: "nested", value: { b: 2 }
// key: "", value: { a: 1, nested: { b: 2 } }  ← last

Parsing Errors

// Syntax error
try {
  JSON.parse("{name: 'John'}");  // Keys must be quoted
} catch (error) {
  console.error(error);
  // SyntaxError: Unexpected token n in JSON at position 1
}

// Unclosed string
JSON.parse('{"name": "John}');  // SyntaxError

// Trailing comma
JSON.parse('{"a": 1,}');  // SyntaxError

// Valid JSON
JSON.parse('{"name":"John"}');  // OK

JSON is Stricter Than JavaScript:

  • Keys must be in double quotes
  • Cannot use trailing commas
  • Only double quotes for strings
  • No comments

Deep Clone with JSON

Simple Cloning Method

const original = {
  name: 'John',
  address: {
    city: 'New York'
  }
};

const clone = JSON.parse(JSON.stringify(original));

clone.address.city = 'Boston';

console.log(original.address.city);  // 'New York' 
console.log(clone.address.city);     // 'Boston' 

Method Limitations

const obj = {
  date: new Date(),
  fn: () => {},
  undef: undefined,
  map: new Map([[1, 'one']]),
  set: new Set([1, 2])
};

const clone = JSON.parse(JSON.stringify(obj));

console.log(clone);
// { date: '2024-01-15T12:00:00.000Z' }  ← Date became string
// fn, undef, map, set — lost

Proper Deep Clone

For full cloning, use structuredClone() (modern standard):

const original = {
  date: new Date(),
  map: new Map([[1, 'one']]),
  set: new Set([1, 2])
};

const clone = structuredClone(original);

console.log(clone.date instanceof Date);  // true 
console.log(clone.map instanceof Map);    // true 

Practical Examples

LocalStorage

// Saving
const user = { name: 'John', settings: { theme: 'dark' } };
localStorage.setItem('user', JSON.stringify(user));

// Loading
const loadedUser = JSON.parse(localStorage.getItem('user'));

API Requests

fetch('/api/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'John', age: 25 })
})
  .then(response => response.json())
  .then(data => console.log(data));

Object Comparison

function deepEqual(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}

deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 });  // true
deepEqual({ a: 1, b: 2 }, { b: 2, a: 1 });  // false (key order matters)

Caution:

This method works only for simple objects and depends on key order.


Performance

const bigObject = { /* 10000 properties */ };

console.time('stringify');
const json = JSON.stringify(bigObject);
console.timeEnd('stringify');  // ~10ms

console.time('parse');
JSON.parse(json);
console.timeEnd('parse');  // ~5ms
  • JSON.parse() is usually faster than JSON.stringify()
  • Can be slow for large objects
  • Consider streaming parsers for huge JSON

Conclusion

JSON.stringify():

  • Serializes objects, arrays, primitives
  • Ignores functions, undefined, Symbol
  • Supports replacer for filtering and transformation
  • Supports space for formatting
  • Can be customized via toJSON()
  • Doesn't work with circular references

JSON.parse():

  • Parses valid JSON
  • Supports reviver for transformation
  • Stricter than JavaScript (quotes, trailing commas)
  • Can throw SyntaxError

Deep Clone via JSON:

  • Simple method
  • Loses functions, Date, Map, Set
  • Use structuredClone() for full cloning

In Interviews:

Common questions:

  • What gets lost with JSON.stringify()?
  • How to handle circular references?
  • What's the difference between JSON.parse() and eval()?
  • How to make a deep clone?
  • What are replacer and reviver for?
Practice JS Problems