Reading data you did not write
Parsing succeeds far more often than the data is usable, and the gap is where bugs live.
Parsed is not valid
JSON.parse tells you the text was well-formed. It tells you nothing about whether the object has the fields you need, whether a number is in range, or whether a string is a URL. Treating a parse as validation is how a missing field becomes undefined and travels three functions before it fails somewhere unrelated.
Check the shape at the boundary, where the data arrives, and turn it into your own type there. Then a fault is reported as "the response had no id" at the place it came in, rather than "cannot read property of undefined" somewhere that had nothing to do with it.
The keys you are not expecting
A document you did not write can contain any key, including __proto__ and constructor. Merging such an object into another with a naive deep merge can alter the prototype every object in the program inherits from — prototype pollution, and it is a real vulnerability class rather than a theoretical one.
JSON.parse itself is safe: it makes a plain object and an own property called __proto__ does not change anything. The danger is what you do next — deep merges, "assign these settings into the defaults" helpers, and anything that walks keys recursively.
Use a validator that names the fields you want and drops the rest. Naming what you accept is both the safest and the clearest option: unknown keys never reach anything that could be surprised by them.
Size is part of the shape
A body with no size limit is a denial-of-service waiting to happen, and so is an array with no length limit: a hundred thousand rows will parse happily and then exhaust memory somewhere further along.
Limit the request size at the edge, cap array lengths and string lengths when you validate, and decide what should happen when a limit is hit — a clear error is far better than a process that dies. This is the kind of thing that never matters until one day it is the whole outage.
Worked examples
Validate at the boundary
/const id = typeof raw.id === "string" ? raw.id : null;/Against:
Rather than trusting raw.id downstreamThe fault is then reported where the data arrived, not three functions later with a useless message.
Check yourself
Practice questions written for this lesson — not past exam papers.
Practise every question in this subject
What does a successful JSON.parse guarantee?
Where does prototype pollution actually happen?