Why JSON keeps coming up in interviews
JSON isn't a hard topic, which is exactly why it's a good interview filter — it tests whether you actually understand the format you use every day, or just know the shape of { "key": "value" } and nothing past it. The questions below cluster into three levels: fundamentals (what JSON actually is), practical gotchas (where it silently differs from the language you're using it in), and system-design adjacent questions (why teams choose the shapes they choose).
Fundamentals
What data types does JSON support?
Exactly six: string, number, boolean, null, object, and array. That's it — no date type, no undefined, no NaN/Infinity, no functions, no Symbols, no Map/Set. Every one of those has to be represented as one of the six (usually a string) and reconstructed by convention on the reading side.
Is a JSON object the same as a JavaScript object?
No, and this trips people up because the syntax looks identical. A JSON object is a serialization format — a string. A JavaScript object is a live, in-memory data structure with a prototype chain, methods, getters, and reference identity. JSON.parse turns the former into the latter; JSON.stringify does the reverse, and the reverse is lossy — functions, undefined values, and Symbol keys are silently dropped, not converted.
JSON.stringify({ a: undefined, b: () => {}, c: 1 });
// => '{"c":1}' — a and b are gone, not "undefined"/"null"Why doesn't JSON support comments?
JSON's designer (Douglas Crockford) left comments out deliberately, reasoning that people would abuse them to embed parsing directives instead of using them as comments — and that a comment-free format is easier to implement consistently everywhere. This is also why config files like tsconfig.json that *do* allow comments are technically JSONC (JSON with Comments), a JSON superset, not strict JSON.
Practical gotchas
How do you safely parse JSON that might be invalid?
Wrap it — JSON.parse throws a SyntaxError on malformed input rather than returning null or an error object, which surprises people used to APIs that return a result type.
function safeParse(text) {
try {
return { ok: true, value: JSON.parse(text) };
} catch (e) {
return { ok: false, error: e.message };
}
}Why did a large integer come back wrong after a JSON round-trip?
JSON numbers have no size limit in the spec, but JSON.parse in JavaScript deserializes every number into a 64-bit IEEE 754 double — which loses precision above Number.MAX_SAFE_INTEGER (2^53 - 1, or 9,007,199,254,740,991). A 64-bit database ID or a Snowflake ID easily exceeds that. The fix is to encode the ID as a string in the JSON, not a bare number — which is exactly what Twitter/X's API and most systems dealing with 64-bit IDs do ("id": "1234567890123456789" alongside a truncated numeric id field, for compatibility).
Can a JSON object have duplicate keys?
The grammar doesn't forbid it, but the spec explicitly says behavior is undefined when it happens — in practice, every parser just keeps the *last* occurrence and silently drops the earlier ones.
JSON.parse('{"role":"user","role":"admin"}');
// => { role: "admin" } — no error, no warningThis has been a real vector for security bugs — an API gateway validating one role key and a backend parser reading a different one from the same string is a classic request-smuggling-style inconsistency.
Does key order matter in a JSON object?
Per the spec, no — an object is an *unordered* collection of key/value pairs. In practice, every major JSON parser (V8's included) preserves and iterates insertion order as an implementation detail, and plenty of code has come to depend on that — which is a common interview follow-up: "should you rely on this?" The honest answer is: for insertion order, mostly yes in modern engines; for an *ordering being meaningful* (e.g., "first key wins"), no — a spec-compliant parser can legally do anything with it.
System-design adjacent questions
Why did REST APIs settle on JSON over XML?
Smaller payloads for equivalent data (no closing tags, no attribute-vs-element ambiguity), a direct mapping to native data structures in JavaScript (and easy-enough mapping in most other languages), and human-readability without a schema. XML still wins in enterprise/SOAP contexts that need namespaces, strict schema validation (XSD), or mixed content — but for a browser-facing API, JSON has been the default for well over a decade.
How would you design a paginated JSON API response?
The two dominant shapes: offset-based ({"data": [...], "page": 2, "perPage": 20, "total": 341}) — simple, but page 2 can shift if rows are inserted/deleted mid-list — and cursor-based ({"data": [...], "nextCursor": "eyJpZCI6NDJ9"}) — stable under concurrent writes, standard in high-scale APIs (Stripe, GitHub's GraphQL API), at the cost of not supporting "jump to page 7" directly.
How do you version a JSON API without breaking existing clients?
Add fields, never remove or repurpose one — old clients that don't know about a new key simply ignore it, since JSON parsing is inherently additive-tolerant. Removing or changing the type of an existing field is the breaking change that needs an actual version bump (a URL path like /v2/, a header, or a date-based version like Stripe's).