Lesson 2 of 3 · Local Persistence (localStorage)
JSON.stringify & JSON.parse
Convert arrays and objects to strings for storage, then restore them safely.
This lesson is locked. You can read ahead, but finish earlier stops to earn progress.
Listen
Watch
Read
Why conversion is necessary
Browser localStorage stores strings only. If you try to save an array or object directly, JavaScript converts it to an unhelpful generic string rather than preserving its structure. JSON provides a standard text format for representing common data such as arrays, objects, numbers, strings and booleans.
Use JSON.stringify(value) before saving structured state. The result is text, so it can be passed to setItem. When you read that text later, use JSON.parse(text) to reconstruct the JavaScript value. This conversion is what lets your quest preserve an XP calculator’s array or object through refreshes.
Save and restore structured state
const progress = { xp: 120, badges: ['first'] };
localStorage.setItem('progress', JSON.stringify(progress));
const raw = localStorage.getItem('progress');
const restored = raw ? JSON.parse(raw) : null;The saved value is JSON text, not a live object. After parsing, restored.xp is available like a normal property. Choose a default when the key is missing, and make sure the data shape your code expects is actually present.
Handle damaged or old data
Parsing can fail if the stored string is not valid JSON. Data may have been edited, partially written or created by an older version of your app. A failed parse throws an error, so protect the read with try/catch and fall back to a safe default.
let progress = { xp: 0 };
try {
const raw = localStorage.getItem('progress');
if (raw) progress = JSON.parse(raw);
} catch (error) {
console.warn('Could not restore saved progress');
}The fallback keeps the app usable instead of leaving a blank screen. For real apps, also validate the parsed shape: valid JSON can still have missing fields or unexpected values.
Apply the round trip
Think of storage as a round trip: JavaScript value → JSON text → browser storage → JSON text → JavaScript value. Stringify on the way in; parse on the way out. Refresh your activity to check the restored state, then test with a missing or invalid key so the recovery path works too.
JSON is for serialisable data, not every JavaScript value. Functions and some special objects do not round-trip as expected, so save the plain data your interface needs rather than behaviour or browser-specific objects.
Valid JSON can still be the wrong data
These strings all parse successfully: '"hello"', '{"quantities":"lots"}' and '[2,-1,"3"]'. None is automatically a usable array of item counts. After parsing, validate the shape and each value, not only whether parsing succeeded.
For a small fixed-length practice list:
function usableQuantities(value, expectedLength) {
return Array.isArray(value)
&& value.length === expectedLength
&& value.every((quantity) =>
Number.isInteger(quantity) && quantity >= 0
);
}Use the expected number of your practice items. If the guard fails, choose fresh defaults rather than applying untrusted content. A stable-ID mapping is often better when a product list can change: a saved index from an old ordering may refer to the wrong product. Do not migrate old state blindly.
Prove save, startup restore and recovery
The startup order matters: read/parse/check → initialise quantities → render inputs → calculate total. If you save defaults before reading, you can overwrite the visitor's previous choice. The change order is read current inputs → calculate → stringify → save.
Use DevTools Application/Storage to inspect your own site's key. Change a harmless quantity, refresh and confirm it returns. Remove that one key and refresh: defaults should appear. Set that practice key to broken JSON and retest; then set it to valid JSON of the wrong shape and retest. Both should recover without a blank app. Restore or remove your test data afterward.
setItem can throw when storage is restricted or full, not only parse. Catch the write as well and allow the in-memory calculator to keep working; do not promise saving succeeded when it did not. Before activity 2.3, explain which failure is syntax, which is shape and which is storage availability, and demonstrate your own refresh/recovery behaviour.
Key terms
- JSON
- A text format for representing structured data.
- JSON.stringify
- Converts a serialisable JavaScript value into JSON text.
- JSON.parse
- Converts valid JSON text into a JavaScript value.
- try/catch
- A control structure for handling errors without stopping the app.
Summary — copy into your notes
- LocalStorage keeps strings, not live objects.
- Stringify structured values before saving.
- Parse stored JSON when restoring state.
- Use try/catch and a default for broken or missing data.