Table of Contents
JSON (JavaScript Object Notation) is the lingua franca of modern software. APIs return it, databases store it, configuration files use it, and message queues carry it. Every web developer touches JSON dozens of times a day — yet the format is subtle enough that even experienced engineers hit parsing errors that take minutes to diagnose.
This guide covers everything you need to use JSON confidently: the exact rules that distinguish JSON from JavaScript object literals, how parsers behave on edge cases, how to validate JSON at the format level and the schema level, how to convert between JSON and other data formats (CSV, YAML, XML), and the most common mistakes and how to avoid them.
All tools referenced here process data entirely in your browser. Nothing is uploaded, and nothing is stored.
What JSON Is — and What It Is Not
JSON is a text-based data serialisation format defined in RFC 8259. It represents structured data using six value types: strings, numbers, booleans, null, objects (unordered key-value maps), and arrays (ordered sequences). That is the complete list — JSON has no dates, no functions, no comments, no undefined, and no binary data type.
JSON is often confused with JavaScript object literal syntax. They share surface-level similarity — both use curly braces for objects and square brackets for arrays — but JSON is stricter in every dimension:
- Keys must be double-quoted strings.
{ name: "Alice" }is valid JavaScript but invalid JSON. - String values must use double quotes. Single quotes are not permitted anywhere in JSON.
- Trailing commas are forbidden.
[1, 2, 3,]is valid JavaScript (since ES5) and invalid JSON. - Comments are not allowed. Neither
//nor/* */comments exist in JSON. - Numbers follow strict rules. Leading zeros (
007), hexadecimal (0xFF),Infinity, andNaNare not valid JSON numbers. - Control characters must be escaped. Raw newlines, tabs, and other control characters inside string values must be written as escape sequences (
\n,\t, etc.).
The practical consequence: JavaScript code that builds an object literal and then runs JSON.stringify() on it produces valid JSON. JavaScript code that hardcodes a "JSON-looking" object literal with comments, trailing commas, or unquoted keys is not JSON — it is a JavaScript expression.
JSON Syntax Reference
String: A sequence of Unicode characters enclosed in double quotes. Special characters must be escaped:
| Character | Escape |
|---|---|
| Quotation mark | \" |
| Backslash | \\ |
| Newline | \n |
| Tab | \t |
| Carriage return | \r |
| Any Unicode code point | \uXXXX |
Number: An integer or floating-point value with optional exponent. No leading zeros. No trailing decimal point. Examples: 42, -3.14, 1.5e10.
Boolean: Exactly true or false (lowercase only).
Null: Exactly null (lowercase only).
Object: Zero or more comma-separated key-value pairs enclosed in {}. Keys are strings. Values can be any JSON value. Key order is not guaranteed — parsers may return keys in any order. Duplicate keys are technically allowed by the specification but produce implementation-dependent behaviour; treat them as an error.
Array: Zero or more comma-separated values enclosed in []. Values can be of mixed types. Order is preserved.
Root value: RFC 8259 allows any JSON value at the root level, not just objects and arrays. "hello", 42, and true are each valid complete JSON documents. Older parsers (RFC 4627) required an object or array at the root; modern parsers follow RFC 8259.
Parsing JSON: What Happens Inside
A JSON parser works in two phases: lexing (breaking the input into tokens) and parsing (constructing the value tree from tokens).
Lexing scans the input character by character, producing tokens: {, }, [, ], :, ,, string literals, number literals, and the keywords true, false, null. Whitespace (space, tab, newline, carriage return) between tokens is ignored.
Parsing uses a recursive-descent approach to build the value tree. An opening { starts an object context; the parser reads alternating string-colon-value sequences separated by commas until }. An opening [ starts an array context; the parser reads comma-separated values until ].
What happens with syntax errors: A well-behaved parser throws on the first error it encounters, including the position (line and column or character offset). The position points to where the parser was when it detected the problem — which is often one or two characters after the actual mistake. A trailing comma before } is flagged on the } character, not the comma.
Number precision: JSON numbers have no inherent precision limit. However, JSON parsers in most languages parse numbers into IEEE 754 double-precision floats by default. Integers beyond 2^53 lose precision in double-precision representation. If you need exact large integers, transmit them as strings or use a parser that supports BigInt (Node.js JSON.parse() gained BigInt support via a reviver function).
Date handling: JSON has no date type. Dates are conventionally transmitted as ISO 8601 strings ("2026-02-17T09:00:00Z"). The receiving application is responsible for parsing the string into a date object. Always agree on the string format in your API contract.
Validation: Format vs Schema
JSON validation has two distinct levels that solve different problems.
Syntax validation confirms the text is well-formed JSON. It checks brackets, quotes, commas, and value syntax. Syntax validation answers: "Can any JSON parser read this?" A syntax validator does not care whether the data makes sense for your application — it only confirms the format is correct. This is what a JSON formatter/validator tool does.
Schema validation confirms the data conforms to a defined structure. It checks that required fields exist, values have the correct types, strings match expected patterns, numbers fall within ranges, and arrays contain the right element types. Schema validation answers: "Does this JSON have the shape my application expects?"
JSON Schema is the standard for schema validation. A JSON Schema is itself a JSON document that describes the expected shape:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"additionalProperties": false
}Key JSON Schema keywords: type, required, properties, items (for arrays), minimum/maximum, minLength/maxLength, pattern (regex), enum, const, anyOf, allOf, oneOf.
When to validate: Always validate API inputs at the server boundary. Never trust client-supplied JSON. For internal service communication, validate during development to catch contract drift early; relax validation in production if performance is critical. Always validate third-party API responses in the consuming service — external APIs change without notice.
Validate JSON online— Exact error positions, no uploadJSON Data Conversions
JSON rarely lives in isolation — data flows between JSON and other formats constantly.
CSV to JSON: CSV is tabular — rows and columns. Converting to JSON produces an array of objects where each row becomes an object with column headers as keys. The tricky part is type inference: CSV has no types, so every value is a string. A good converter infers that "42" should become the number 42, "true" should become the boolean true, and "" should become null. Always verify inferred types when precision matters.
JSON to CSV: The inverse. Only works cleanly when the JSON is an array of flat objects with the same keys. Nested objects and arrays cannot be directly represented in CSV — they are either stringified (ugly) or the conversion is refused. Flatten nested structures before converting.
YAML to JSON: YAML is a superset of JSON in terms of what it can represent, plus it adds comments, anchors, aliases, multi-line strings, and block syntax. Converting YAML to JSON loses comments and collapses anchors. Most YAML in practice (Kubernetes configs, Docker Compose, GitHub Actions) converts cleanly to JSON.
JSON to YAML: The inverse. All JSON is valid YAML, so conversion is lossless. The output typically uses YAML block syntax (indented, no quotes for simple strings) rather than flow syntax (inline, JSON-like). Useful when the output needs to be human-edited.
XML to JSON: XML and JSON have fundamentally different models — XML has attributes, mixed content (text + child elements), namespaces, and processing instructions. There is no universal XML-to-JSON mapping. The most common approach is the "BadgerFish" or similar convention: attributes become keys prefixed with @, text content becomes a #text key. Always verify the mapping convention used by your converter.
Most Common JSON Mistakes
1. Trailing commas. The single most common JSON error. { "a": 1, "b": 2, } is invalid. JavaScript engines accept trailing commas since ES5; JSON does not. Linters like ESLint catch trailing commas in JS source but not in .json files unless specifically configured. Fix: always run a JSON validator before committing JSON files.
2. Single-quoted strings. { 'key': 'value' } is invalid JSON. This error is common when developers copy Python dict literals or JavaScript object literals directly into JSON files.
3. Unquoted keys. { key: "value" } is valid JavaScript but invalid JSON. Keys must be double-quoted strings.
4. JavaScript keywords. undefined is not a JSON value. JSON.stringify({ a: undefined }) returns "{}" — the key is silently dropped. Infinity serialises to null. NaN serialises to null. This is a JavaScript behaviour, not a JSON feature.
5. Encoding issues. JSON must be encoded in UTF-8, UTF-16, or UTF-32. UTF-8 is the standard. If a JSON string contains characters that are not properly encoded, parsers may fail at the character boundary. Non-ASCII characters in JSON strings must be in the string as-is (UTF-8 encoded) or escaped as \uXXXX sequences.
6. Large numbers losing precision. 9007199254740993 (2^53 + 1) parses as 9007199254740992 in JavaScript because double-precision floats cannot represent it exactly. Snowflake-style IDs (Twitter, Discord) exceed 2^53 and must be transmitted as strings in JSON APIs.
7. Assuming key order. JSON objects are unordered. { "a": 1, "b": 2 } and { "b": 2, "a": 1 } are semantically identical. Code that depends on key insertion order is relying on implementation-specific behaviour. If order matters, use an array.
8. Deeply nested structures. Most JSON parsers have a recursion depth limit (typically 500–1000 levels). JSON documents with extreme nesting depth may hit this limit. In practice, any structure needing more than 20 levels of nesting should be redesigned.
JSON in APIs: Practical Patterns
Content-Type header: JSON APIs must send Content-Type: application/json on both request and response. Without it, some clients default to form-encoded parsing and others refuse to parse the body.
Error responses: Standardise your error JSON shape. A common pattern: { "error": { "code": "NOT_FOUND", "message": "Resource not found", "details": {} } }. Pick one shape and use it everywhere — inconsistent error formats are the leading cause of client-side parsing bugs.
Pagination: Three common patterns: cursor-based ({ "data": [...], "next_cursor": "abc123" }), offset-based ({ "data": [...], "total": 500, "offset": 20, "limit": 20 }), and page-based ({ "data": [...], "page": 3, "total_pages": 25 }). Cursor-based is the most stable for large, frequently-changing datasets.
Envelope vs flat: Some APIs wrap all responses in { "data": ... }; others return the resource directly. Either works — be consistent within an API.
Versioning: /api/v1/users vs /api/v2/users is the standard. Breaking changes (removing fields, changing types) require a new version. Adding new optional fields to existing responses is backward-compatible.
Null vs missing key: { "bio": null } and {} (bio key absent) are different. The first explicitly says the field has no value; the second says the field is unknown or not applicable. Treat them differently in your application logic and document which one your API returns.
Frequently Asked Questions
What is the difference between JSON and JSON5?
Is JSON case-sensitive?
How do I represent binary data in JSON?
Can JSON keys be numbers?
What is JSONL (JSON Lines)?
Why does JSON.parse throw 'Unexpected token' errors?
Summary
JSON's simplicity — six value types, two container types, one encoding — is what makes it universal. Understanding the exact rules (double quotes, no trailing commas, no comments, no undefined) prevents the common mistakes that cause silent data loss or parse failures at the worst possible time. Add schema validation at your API boundaries, keep your structures flat where possible, and use a formatter to catch syntax errors before they reach production.