Complete Guide to JSON: Everything Developers Need to Know
I've spent more time debugging JSON issues than I care to admit. At my last startup, we had an API that would randomly fail with cryptic "unexpected token" errors. Turns out, someone was manually editing config files and occasionally adding trailing commas. JSON doesn't forgive trailing commas. Neither did our customers when the service went down.
Let me save you from making the same mistakes. This guide covers everything you need to know about JSON, from basic syntax to production-ready practices.
What is JSON?
JSON (JavaScript Object Notation) is a lightweight data interchange format that's easy for humans to read and write, and easy for machines to parse and generate. Despite having "JavaScript" in its name, JSON is language-independent and supported by virtually every programming language.
It's become the de facto standard for web APIs, configuration files, and data storage because it strikes the perfect balance between simplicity and expressiveness.
JSON Syntax Basics
Data Types
JSON supports six data types:
1. Strings - Must use double quotes (not single quotes)
{ "name": "Sarah Chen", "role": "Senior Developer" }
2. Numbers - Integers or floats, no quotes
{ "age": 32, "experience": 12.5, "rating": 4.8 }
3. Booleans - true or false (lowercase, no quotes)
{ "isActive": true, "hasAccess": false }
4. Null - Represents the absence of a value
{ "middleName": null, "previousEmployer": null }
5. Arrays - Ordered lists of values
{ "skills": ["React", "Node.js", "PostgreSQL"], "scores": [95, 88, 92] }
6. Objects - Unordered collections of key-value pairs
{ "user": { "name": "Sarah", "contact": { "email": "[email protected]", "phone": "+1-555-0123" } } }
Critical Syntax Rules
JSON is stricter than JavaScript. Here are the rules that catch most developers:
Keys must be strings in double quotes:
// ✅ Valid {"name": "Sarah"} // ❌ Invalid {name: "Sarah"} {'name': 'Sarah'}
No trailing commas:
// ✅ Valid { "name": "Sarah", "age": 32 } // ❌ Invalid - trailing comma { "name": "Sarah", "age": 32, }
Strings must use double quotes:
// ✅ Valid {"message": "Hello, world!"} // ❌ Invalid - single quotes {"message": 'Hello, world!'}
No comments allowed: JSON doesn't support comments. This is intentional—JSON is a data format, not a configuration language. Use separate documentation or alternative formats like JSON5 if you need comments.
Common Real-World Use Cases
1. API Request and Response Bodies
// POST /api/users request body { "email": "[email protected]", "name": "Sarah Chen", "preferences": { "newsletter": true, "notifications": { "email": true, "push": false } } } // Response { "success": true, "data": { "id": "usr_12345", "email": "[email protected]", "createdAt": "2026-01-15T10:30:00Z" } }
2. Configuration Files
Many tools use JSON for configuration (package.json, tsconfig.json, etc.):
{ "name": "my-app", "version": "1.0.0", "scripts": { "start": "node server.js", "test": "jest" }, "dependencies": { "express": "^4.18.0", "dotenv": "^16.0.0" } }
3. Data Storage and Exchange
{ "users": [ { "id": 1, "name": "Sarah Chen", "roles": ["admin", "developer"] }, { "id": 2, "name": "Marcus Johnson", "roles": ["developer"] } ] }
JSON Validation: Catching Errors Early
Invalid JSON will break your application. Here's how to validate it properly:
Client-Side Validation (JavaScript)
function isValidJSON(str) { try { JSON.parse(str); return true; } catch (e) { return false; } } // Better: catch and handle the error function parseJSON(str) { try { return { success: true, data: JSON.parse(str) }; } catch (error) { return { success: false, error: error.message, position: error.message.match(/position (\d+)/)?.[1] }; } }
Server-Side Validation (Node.js)
app.post('/api/data', (req, res) => { // Express with body-parser automatically validates JSON // If invalid, it returns 400 Bad Request // Additional schema validation const schema = { email: 'string', age: 'number', preferences: 'object' }; if (!validateSchema(req.body, schema)) { return res.status(400).json({ error: 'Invalid data format' }); } // Process valid data });
Common JSON Pitfalls (and How to Avoid Them)
1. Dates Aren't a Native Type
JSON doesn't have a date type. You'll need to use strings:
{ "createdAt": "2026-01-15T10:30:00Z", "updatedAt": "2026-01-15T14:20:00Z" }
Best practice: Use ISO 8601 format (YYYY-MM-DDTHH:mm:ssZ). It's unambiguous and sortable.
// JavaScript const date = new Date(); const isoString = date.toISOString(); // "2026-01-15T10:30:00.000Z" // Parsing back const parsedDate = new Date(isoString);
2. Numbers Have Limits
JSON numbers follow IEEE 754 double-precision floating-point format. This means:
- Maximum safe integer: 9,007,199,254,740,991 (2^53 - 1)
- Precision loss with very large integers
- Potential floating-point arithmetic issues
// ❌ Problematic - ID too large { "userId": 9007199254740992 // May lose precision } // ✅ Better - use string for large IDs { "userId": "9007199254740992" }
3. Circular References Aren't Supported
const obj = { name: "Sarah" }; obj.self = obj; // Circular reference JSON.stringify(obj); // ❌ TypeError: Converting circular structure to JSON
Solution: Use a library like flatted or manually handle circular references.
4. Function and Undefined Values Are Ignored
const data = { name: "Sarah", age: undefined, greet: function() { return "Hello"; } }; JSON.stringify(data); // Result: {"name":"Sarah"} // undefined and function are silently dropped!
Best Practices for Production Systems
1. Always Validate External JSON
Never trust JSON from external sources:
// Use a schema validation library import Joi from 'joi'; const userSchema = Joi.object({ email: Joi.string().email().required(), age: Joi.number().integer().min(0).max(150), name: Joi.string().max(100).required() }); const { error, value } = userSchema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); }
2. Use Proper Error Handling
// ❌ Bad - swallows errors let data; try { data = JSON.parse(response); } catch (e) { data = {}; } // ✅ Good - handles errors appropriately let data; try { data = JSON.parse(response); } catch (e) { logger.error('JSON parse failed', { error: e.message, response }); return { error: 'Invalid response format' }; }
3. Be Careful with Pretty Printing
// Development: Pretty print for readability JSON.stringify(data, null, 2); // Production: Minify to save bandwidth JSON.stringify(data);
4. Handle Large JSON Files Carefully
For very large JSON files, use streaming parsers to avoid memory issues:
// Node.js - streaming large JSON const StreamArray = require('stream-json/streamers/StreamArray'); const fs = require('fs'); const stream = fs.createReadStream('large-file.json'); const jsonStream = StreamArray.withParser(); stream.pipe(jsonStream.input); jsonStream.on('data', ({ key, value }) => { // Process each item without loading entire file processItem(value); });
JSON vs. Alternatives
JSON vs. XML
JSON wins for:
- Simplicity and readability
- Native browser support
- Smaller payload size
- Easier to parse
XML wins for:
- Complex document structures
- Built-in validation (XSD)
- Metadata and attributes
- Legacy system compatibility
JSON vs. YAML
JSON wins for:
- Strict syntax (fewer errors)
- Better performance
- Universal support
YAML wins for:
- Human readability
- Comments support
- Less verbose syntax
Debugging JSON Efficiently
Online Tools
Use a JSON formatter/validator like the one at qwertywelch.com to:
- Validate syntax
- Format for readability
- Identify error locations
- Minify for production
Command Line
# Validate and pretty-print JSON cat data.json | jq '.' # Extract specific fields cat data.json | jq '.users[0].name' # Validate only cat data.json | jq type >/dev/null
Browser DevTools
Most browsers will prettify JSON responses in the Network tab. Use this to inspect API responses quickly.
Conclusion
JSON is simple, but there are plenty of ways to shoot yourself in the foot. The key lessons:
- Validate everything - Especially external input
- Use proper error handling - Don't silently fail
- Follow conventions - ISO dates, consistent formatting
- Test edge cases - Large numbers, special characters, unicode
- Use tools - Validators, linters, and formatters
I've debugged enough JSON issues to know these practices aren't optional—they're essential for building reliable systems. Take the time to handle JSON properly, and you'll save yourself from those 2 AM debugging sessions trying to figure out why position 1,247 has an "unexpected token."
Trust me on this one.
