Question

How to Store JavaScript Objects in localStorage and sessionStorage

htmljavascriptlocal-storage

Question

I want to store a JavaScript object in HTML5 localStorage, but the object seems to be converted into a string.

I can store and retrieve primitive JavaScript values and arrays, but plain objects do not seem to behave the way I expected. Should storing objects work directly?

Here is the code:

var testObject = { one: 1, two: 2, three: 3 };
console.log('typeof testObject: ' + typeof testObject);
console.log('testObject properties:');
for (var prop in testObject) {
  console.log('  ' + prop + ': ' + testObject[prop]);
}

// Put the object into storage
localStorage.setItem('testObject', testObject);

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('typeof retrievedObject: ' + typeof retrievedObject);
console.log('Value of retrievedObject: ' + retrievedObject);

The console output is:

typeof testObject: object
testObject properties:
  one: 1
  two: 2
  three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]

It looks like setItem() converts the value to a string before storing it.

I see the same behavior in Safari, Chrome, and Firefox, so I assume this is my misunderstanding of Web Storage rather than a browser bug.

Why does this happen, and what is the easiest way to store and retrieve objects correctly using localStorage or sessionStorage?

Short Answer

By the end of this page, you will understand that localStorage and sessionStorage store strings only, not JavaScript objects directly. You will learn how to save objects with JSON.stringify(), restore them with JSON.parse(), avoid common mistakes, and use this pattern safely in real projects.

Concept

localStorage and sessionStorage are part of the Web Storage API. They provide simple key-value storage in the browser.

The important rule is:

  • Keys are strings
  • Values are strings

That means if you pass an object to setItem(), JavaScript converts it to a string first. A plain object becomes:

"[object Object]"

That string is not a real object anymore. It is just text, so when you read it back with getItem(), you get a string.

To store an object properly, you need to:

  1. Convert the object into a JSON string with JSON.stringify()
  2. Save that string in storage
  3. Convert it back into an object with JSON.parse() when reading it

Example:

const user = { name: 'Ava', age: 28 };
localStorage.setItem('user', JSON.stringify(user));

const storedUser = JSON.parse(localStorage.getItem('user'));
console.log(storedUser.name); // Ava

Why this matters in real programming:

  • Browser storage is often used for settings, drafts, tokens, carts, and cached API responses
  • Most useful application data is structured as objects or arrays
  • Knowing how serialization works helps you avoid losing data structure

This is really a concept about serialization: converting data into a format that can be stored or transmitted, then converting it back later.

Mental Model

Think of localStorage like a notebook that only accepts text.

  • If you hand it a number, it writes the number as text
  • If you hand it a boolean, it writes "true" or "false"
  • If you hand it an object, it cannot keep the object structure by itself, so it writes the object's default text form: "[object Object]"

JSON.stringify() is like translating your object into a text format that preserves its structure.

JSON.parse() is like reading that text and rebuilding the original object.

So the flow is:

  • Object in memory -> JSON.stringify() -> JSON text in storage
  • JSON text from storage -> JSON.parse() -> Object in memory
Take Quiz

Syntax and Examples

The basic pattern is:

localStorage.setItem('key', JSON.stringify(value));
const value = JSON.parse(localStorage.getItem('key'));

Store and retrieve an object

const testObject = { one: 1, two: 2, three: 3 };

localStorage.setItem('testObject', JSON.stringify(testObject));

const retrievedObject = JSON.parse(localStorage.getItem('testObject'));

console.log(typeof retrievedObject); // object
console.log(retrievedObject.one);    // 1
console.log(retrievedObject.two);    // 2
console.log(retrievedObject.three);  // 3

Explanation:

  • JSON.stringify(testObject) turns the object into a JSON string such as:
'{"one":1,"two":2,"three":3}'
  • localStorage stores that string
  • JSON.parse(...) turns the JSON string back into an object

The same idea with sessionStorage

const settings = { theme: 'dark', fontSize: 16 };

sessionStorage.setItem('settings', JSON.stringify(settings));

const savedSettings = JSON.parse(sessionStorage.getItem('settings'));
console.log(savedSettings.theme); // dark

Store an array of objects

const products = [
  { id: 1, name: 'Keyboard' },
  { id: 2, name: 'Mouse' }
];

localStorage.setItem('products', JSON.stringify(products));

const savedProducts = JSON.parse(localStorage.getItem('products'));
console.log(savedProducts[0].name); // Keyboard

Safe fallback when data may not exist

const saved = localStorage.getItem('profile');
const profile = saved ? JSON.parse(saved) : null;

This avoids calling JSON.parse() on null.

Step by Step Execution

Consider this example:

const cart = { items: 3, total: 49.99 };
localStorage.setItem('cart', JSON.stringify(cart));
const raw = localStorage.getItem('cart');
const parsed = JSON.parse(raw);

console.log(raw);
console.log(parsed.total);

Step by step:

  1. cart is created as a normal JavaScript object:
{ items: 3, total: 49.99 }
  1. JSON.stringify(cart) converts it to a string:
'{"items":3,"total":49.99}'
  1. localStorage.setItem('cart', ...) stores that string under the key cart

  2. localStorage.getItem('cart') reads the stored value back

  3. The value assigned to raw is still a string:

'{"items":3,"total":49.99}'
  1. JSON.parse(raw) converts the string back into a JavaScript object

  2. parsed.total now works like normal object access and returns 49.99

If you skip JSON.parse(), then raw.total would be undefined because raw is a string, not an object.

Real World Use Cases

Here are common situations where developers store objects in browser storage:

User preferences

const preferences = {
  language: 'en',
  darkMode: true,
  sidebarOpen: false
};

Store these so the app remembers settings after refresh.

Shopping cart data

const cart = {
  items: [
    { id: 101, quantity: 2 },
    { id: 205, quantity: 1 }
  ],
  coupon: 'SAVE10'
};

Useful for preserving cart contents between page reloads.

Form drafts

const draft = {
  title: 'My article',
  body: 'Draft content here...'
};

Helpful in note-taking apps, CMS editors, or long forms.

Cached API responses

const cachedUser = {
  id: 7,
  name: 'Mina',
  role: 'admin'
};

Apps sometimes cache data to reduce unnecessary network requests.

Temporary session-only state

Use sessionStorage for data that should be cleared when the browser tab closes, such as:

  • Multi-step form progress
  • Temporary filters
  • Short-lived UI state
Take Quiz

Real Codebase Usage

In real projects, developers usually do more than just call JSON.stringify() and JSON.parse() directly.

Common wrapper functions

A common pattern is to centralize storage logic:

function saveToStorage(key, value) {
  localStorage.setItem(key, JSON.stringify(value));
}

function loadFromStorage(key) {
  const value = localStorage.getItem(key);
  return value ? JSON.parse(value) : null;
}

This avoids repeating the same code everywhere.

Guard clauses for missing data

function loadCart() {
  const saved = localStorage.getItem('cart');
  if (!saved) return { items: [] };
  return JSON.parse(saved);
}

This prevents crashes when the key does not exist.

Validation after parsing

Storage can contain old, broken, or unexpected data.

function loadSettings() {
  const raw = localStorage.getItem('settings');
  if (!raw) return { theme: 'light' };

  const parsed = JSON.parse(raw);
  if (typeof parsed.theme !== 'string') {
    return { theme: 'light' };
  }

  return parsed;
}

Error handling for invalid JSON

function safeLoad(key) {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) : null;
  } catch (error) {
    console.error('Invalid stored JSON for key:', key, error);
    return null;
  }
}

Updating part of an object

A frequent pattern is read-modify-write:

const user = JSON.parse(localStorage.getItem('user')) || {};
user.lastLogin = Date.now();
localStorage.setItem('user', JSON.stringify(user));

Choosing between localStorage and sessionStorage

Developers often choose based on data lifetime:

  • localStorage: persists until explicitly removed
  • sessionStorage: lasts for the current tab session

Common Mistakes

1. Storing objects without JSON.stringify()

Broken:

const user = { name: 'Sam' };
localStorage.setItem('user', user);

Result:

"[object Object]"

Fix:

localStorage.setItem('user', JSON.stringify(user));

2. Forgetting to JSON.parse() after reading

Broken:

localStorage.setItem('user', JSON.stringify({ name: 'Sam' }));
const user = localStorage.getItem('user');
console.log(user.name); // undefined

Why:

  • user is a string, not an object

Fix:

const user = JSON.parse(localStorage.getItem('user'));
console.log(user.name);

3. Parsing null

Potential issue:

const data = JSON.parse(localStorage.getItem('missingKey'));

If the key does not exist, getItem() returns null. It is better to handle that case clearly.

Safer:

const raw = localStorage.getItem('missingKey');
const data = raw ? JSON.parse(raw) : null;

4. Assuming all values can be serialized cleanly

Not everything works well with JSON:

  • Functions are ignored
  • undefined is omitted in objects
  • Date becomes a string
  • Map and Set do not restore automatically to their original types

Example:

const obj = {
  created: new Date(),
  greet: function () { console.log('hi'); }
};

localStorage.setItem('obj', JSON.stringify(obj));

After parsing, created is a string, and greet is gone.

5. Storing sensitive data insecurely

Avoid putting highly sensitive information in Web Storage, especially if your app may be exposed to XSS.

Examples to be careful with:

  • authentication tokens
  • personal user data
  • payment details

6. Forgetting storage size limits

localStorage is small and not meant for large datasets. It is useful for lightweight client-side data, not full databases.

Comparisons

ConceptWhat it storesPersists after browser restart?Best for
localStorageStringsYesPreferences, carts, cached small data
sessionStorageStringsNoTab-specific temporary state
JavaScript variableAny JS valueNoIn-memory runtime data
CookieStringsUsually yes, if configuredSmall server-related data

localStorage vs sessionStorage

localStorage.setItem('theme', 'dark');
sessionStorage.setItem('step', '2');
  • localStorage remains until removed
  • sessionStorage is cleared when the tab or window session ends

Direct object storage vs JSON serialization

ApproachWorks?Result
localStorage.setItem('x', obj)No, not as expectedStores "[object Object]"
localStorage.setItem('x', JSON.stringify(obj))YesStores JSON text

JSON vs normal string conversion

String({ a: 1 });              // "[object Object]"
JSON.stringify({ a: 1 });      // '{"a":1}'

String() gives a general text representation.

JSON.stringify() preserves the data structure in a useful format.

Take Quiz

Cheat Sheet

// Store an object
localStorage.setItem('key', JSON.stringify(obj));

// Read an object
const raw = localStorage.getItem('key');
const obj = raw ? JSON.parse(raw) : null;

// Remove an item
localStorage.removeItem('key');

// Clear all storage
localStorage.clear();

Rules

  • localStorage stores strings only
  • Objects must be converted with JSON.stringify()
  • Read them back with JSON.parse()
  • The same pattern applies to sessionStorage

Common results

localStorage.setItem('x', { a: 1 });
localStorage.getItem('x');
// "[object Object]"
localStorage.setItem('x', JSON.stringify({ a: 1 }));
localStorage.getItem('x');
// '{"a":1}'

Edge cases

  • Missing key -> getItem() returns null
  • Invalid JSON -> JSON.parse() throws an error
  • Functions are not preserved in JSON
  • Dates come back as strings
  • Large data does not belong in localStorage

Safe helper

function getStoredObject(key) {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) : null;
  } catch {
    return null;
  }
}

FAQ

Can localStorage store JavaScript objects directly?

No. It stores strings only. Use JSON.stringify() before saving and JSON.parse() after reading.

Why do I get "[object Object]" in localStorage?

Because the object was converted using normal string conversion instead of JSON serialization.

Does this also apply to sessionStorage?

Yes. sessionStorage also stores string values only.

Can I store arrays in localStorage?

Yes, but you should still use JSON. Arrays are commonly stored with JSON.stringify() and restored with JSON.parse().

What happens if the key does not exist?

getItem() returns null. You should check for that before parsing.

Can I store functions, dates, or class instances?

Not reliably in their original form. JSON works best with plain data objects, arrays, strings, numbers, booleans, and null.

Is localStorage a good place for sensitive data?

Usually no. Sensitive data in browser storage can be exposed if your site has security issues such as XSS.

What is the easiest pattern to remember?

Save with:

JSON.stringify(value)

Load with:

JSON.parse(storedValue)
Take Quiz

Mini Project

Description

Build a small browser-based preferences saver. The app stores a user's display settings in localStorage and restores them when the page loads. This demonstrates the full cycle of converting an object to JSON, saving it, reading it back, and updating the UI from stored data.

Goal

Create a page that saves and restores a user preferences object using localStorage and JSON methods.

Requirements

  • Create a preferences object with at least username, theme, and notifications properties.
  • Save the preferences object to localStorage when the user clicks a button.
  • Load the saved preferences from localStorage when the page starts.
  • Display the loaded values on the page.
  • Handle the case where no saved preferences exist yet.
Take Quiz

Keep learning

Related questions

View more