# JSON Complete Guide: Data Format and Advanced Processing
Master JSON syntax, parsing methods, Schema validation and performance optimization
JSON is the most widely used data exchange format in modern web development. This article explores advanced JSON usage.
JSON Basics
Syntax Rules
{
"string": "Hello World",
"number": 42,
"float": 3.14,
"boolean": true,
"null": null,
"array": [1, 2, 3],
"object": {
"nested": "value"
}
}
Data Types
JSON Data Types:
┌─────────────────────────────────────────────────────┐
│ │
│ Primitive Types │
│ ├── String "hello" │
│ ├── Number 42, 3.14, -1, 1e10 │
│ ├── Boolean true, false │
│ └── Null null │
│ │
│ Complex Types │
│ ├── Object {"key": "value"} │
│ └── Array [1, 2, 3] │
│ │
│ Not Supported │
│ ├── undefined │
│ ├── Function │
│ ├── Symbol │
│ ├── Date (must convert to string) │
│ └── Comments │
│ │
└─────────────────────────────────────────────────────┘
Syntax Key Points
// Correct JSON
{
"name": "John", // Keys must use double quotes
"age": 30 // No trailing comma on last item
}
// Invalid examples
{
name: "John", // Error: unquoted key
'age': 30, // Error: single quotes
"city": "NYC", // Error: trailing comma
}
JSON in JavaScript
Parsing and Serialization
// JSON.parse - string to object
const jsonString = '{"name":"John","age":30}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // "John"
// JSON.stringify - object to string
const data = { name: 'John', age: 30 };
const str = JSON.stringify(data);
console.log(str); // '{"name":"John","age":30}'
// Formatted output
const formatted = JSON.stringify(data, null, 2);
console.log(formatted);
// {
// "name": "John",
// "age": 30
// }
Advanced Options
// replacer function - custom serialization
const user = {
name: 'John',
password: 'secret',
age: 30
};
const safe = JSON.stringify(user, (key, value) => {
if (key === 'password') return undefined;
return value;
});
// '{"name":"John","age":30}'
// replacer array - select fields
const partial = JSON.stringify(user, ['name', 'age']);
// '{"name":"John","age":30}'
// reviver function - custom parsing
const dateStr = '{"created":"2025-01-28T00:00:00.000Z"}';
const withDate = JSON.parse(dateStr, (key, value) => {
if (key === 'created') return new Date(value);
return value;
});
console.log(withDate.created instanceof Date); // true
Deep Copy
// Simple deep copy (with limitations)
const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));
// Limitations:
// - Cannot copy functions
// - Cannot copy undefined
// - Cannot copy circular references
// - Date becomes string
// - Map/Set become empty objects
// Better solution
const betterCopy = structuredClone(original);
Type-Safe JSON
TypeScript Types
// Define data type
interface User {
id: number;
name: string;
email: string;
createdAt: string;
}
// Type-safe parsing
function parseUser(json: string): User {
const data = JSON.parse(json);
// Validate required fields
if (typeof data.id !== 'number') {
throw new Error('Invalid id');
}
if (typeof data.name !== 'string') {
throw new Error('Invalid name');
}
return data as User;
}
// Using type guards
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'name' in data &&
'email' in data
);
}
const parsed = JSON.parse(jsonString);
if (isUser(parsed)) {
console.log(parsed.name); // Type safe
}
Zod Validation
import { z } from 'zod';
// Define Schema
const UserSchema = z.object({
id: z.number(),
name: z.string().min(1),
email: z.string().email(),
age: z.number().optional(),
role: z.enum(['admin', 'user']).default('user')
});
type User = z.infer<typeof UserSchema>;
// Safe parsing
function parseUserSafe(json: string): User {
const data = JSON.parse(json);
return UserSchema.parse(data);
}
// Or use safeParse
const result = UserSchema.safeParse(JSON.parse(json));
if (result.success) {
console.log(result.data);
} else {
console.error(result.error);
}
JSON Schema
Defining Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
},
"required": ["id", "name", "email"],
"additionalProperties": false
}
Validation with Ajv
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string', format: 'email' },
age: { type: 'number', minimum: 0 }
},
required: ['name', 'email']
};
const validate = ajv.compile(schema);
const data = { name: 'John', email: 'john@example.com', age: 30 };
if (validate(data)) {
console.log('Valid!');
} else {
console.log('Errors:', validate.errors);
}
Large JSON Processing
Streaming Parsing
// For very large JSON files
import { createReadStream } from 'fs';
import { parser } from 'stream-json';
import { streamArray } from 'stream-json/streamers/StreamArray';
async function processLargeJson(filePath: string) {
const pipeline = createReadStream(filePath)
.pipe(parser())
.pipe(streamArray());
for await (const { value } of pipeline) {
// Process array elements one by one
console.log(value);
}
}
Performance Optimization
// Avoid repeated parsing
const cache = new Map<string, unknown>();
function parseWithCache(json: string): unknown {
if (cache.has(json)) {
return cache.get(json);
}
const result = JSON.parse(json);
cache.set(json, result);
return result;
}
// Lazy parsing
class LazyJson<T> {
private json: string;
private parsed: T | null = null;
constructor(json: string) {
this.json = json;
}
get value(): T {
if (this.parsed === null) {
this.parsed = JSON.parse(this.json);
}
return this.parsed;
}
}
// Selective parsing
function extractField(json: string, field: string): string | null {
// For simple cases, regex might be faster
const regex = new RegExp(`"${field}"\\s*:\\s*"([^"]*)"`)
const match = json.match(regex);
return match ? match[1] : null;
}
JSON and APIs
Request and Response
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}
async function fetchJson<T>(url: string): Promise<T> {
const response = await fetch(url, {
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
async function postJson<T, R>(url: string, data: T): Promise<R> {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
Error Handling
function safeJsonParse<T>(
json: string,
fallback: T
): T {
try {
return JSON.parse(json) as T;
} catch {
return fallback;
}
}
// Usage
const config = safeJsonParse(
localStorage.getItem('config') || '',
{ theme: 'light', fontSize: 14 }
);
Best Practices Summary
JSON Best Practices:
┌─────────────────────────────────────────────────────┐
│ │
│ Security │
│ ├── Always validate input data │
│ ├── Use Schema validation │
│ ├── Handle parse errors │
│ └── Avoid storing sensitive info │
│ │
│ Performance │
│ ├── Stream parse large files │
│ ├── Cache parsed results │
│ ├── Avoid repeated serialization │
│ └── Consider compressed transfer │
│ │
│ Maintainability │
│ ├── Define clear types │
│ ├── Document with Schema │
│ ├── Version API responses │
│ └── Provide clear error messages │
│ │
└─────────────────────────────────────────────────────┘
| Method | Purpose |
|---|---|
| JSON.parse() | Parse JSON string |
| JSON.stringify() | Serialize to JSON |
| structuredClone() | Deep copy |
| Zod/Ajv | Schema validation |
JSON is simple yet powerful - mastering it is fundamental to frontend development.