JSON Processing in TypeScript: Typing, Validation, and Parsing

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

JSON Processing in TypeScript: From Basic Operations to Advanced Typing



JSON (JavaScript Object Notation) remains the primary data exchange format in web development. TypeScript adds a powerful type system to working with JSON, which helps avoid many errors at the compilation stage. In this article, we will cover all aspects of JSON processing in TypeScript: from simple parsing to creating strictly typed validators.



Basic Parsing and Serialization



Let's start with fundamental operations. The built-in methods JSON.parse() and JSON.stringify() work in TypeScript the same way as in JavaScript, but with important differences in typing.



// Simple parsing — the result will be anyconst data: any = JSON.parse('{"name": "Alice", "age": 30}');

// Better to specify the type immediatelyinterface User { name: string; age: number;}

const user: User = JSON.parse('{"name": "Alice", "age": 30}') as User;console.log(user.name); // Alice


It's important to understand: as User is a type assertion, not a validation. If the JSON contains invalid data, TypeScript will not warn you about the error. Validation is needed for safe operation.



Safe Parsing with Generics



Let's create a universal function for safe JSON parsing with structure validation:



function safeParse<T>(json: string, validator: (data: unknown) => data is T): T | null {  try {    const parsed: unknown = JSON.parse(json);    if (validator(parsed)) {      return parsed;    }    return null;  } catch {    return null;  }}

// Define the type and validator functioninterface Product { id: number; title: string; price: number;}

function isProduct(data: unknown): data is Product { if (typeof data !== 'object' || data === null) return false; const obj = data as Record<string, unknown>; return ( typeof obj.id === 'number' && typeof obj.title === 'string' && typeof obj.price === 'number' );}

const jsonString = '{"id": 1, "title": "Book", "price": 19.99}';const product = safeParse<Product>(jsonString, isProduct);if (product) { console.log(`Product: ${product.title}, price: ${product.price}`);} else { console.log('Invalid JSON format');}


Working with Nested Structures and Arrays



Real JSON data often contains nested objects and arrays. Let's look at an example with typing a complex structure:



interface Order {  id: string;  customer: {    name: string;    email: string;  };  items: Array<{    productId: number;    quantity: number;  }>;  total: number;}

// Parse and immediately check the structurefunction parseOrder(json: string): Order { const raw = JSON.parse(json); // Simple validation if (!raw.id || !raw.customer || !Array.isArray(raw.items)) { throw new Error('Invalid order structure'); } return raw as Order;}

const orderJson = `{ "id": "ORD-001", "customer": {"name": "Bob", "email": "bob@example.com"}, "items": [{"productId": 42, "quantity": 2}], "total": 59.98}`;

try { const order = parseOrder(orderJson); console.log(`Order ${order.id} for a total of ${order.total}`);} catch (e) { console.error('Parsing error:', e.message);}


Serialization with Custom Transformers



Sometimes you need to control how objects are converted to JSON. TypeScript allows creating custom serializers:



interface Config {  host: string;  port: number;  timeout: number; // in milliseconds}

function serializeConfig(config: Config): string { return JSON.stringify({ host: config.host, port: config.port, timeout: config.timeout / 1000 // convert to seconds }, null, 2); // formatting with indentation}

const myConfig: Config = { host: 'localhost'

Recommendations