Master JSON data manipulation in JavaScript. Learn parsing, validation, transformation, and handling complex data structures from APIs.
JSON (JavaScript Object Notation) is the universal language of web APIs. While its name suggests a connection to JavaScript, JSON has become the standard data exchange format across all programming languages and platforms.
JSON (JavaScript Object Notation) is a lightweight, text-based data interchange format. Despite its name suggesting JavaScript origins, JSON is language-independent and has become the standard for web APIs.
JSON syntax rules:
JSON data types:
1{
2 "string": "Hello World",
3 "number": 42,
4 "boolean": true,
5 "null_value": null,
6 "object": {
7 "nested": "value"
8 },
9 "array": [1, 2, 3, "mixed", true]
10}Valid JSON example:
1{
2 "user": {
3 "id": 12345,
4 "username": "johndoe",
5 "email": "[email protected]",
6 "profile": {
7 "firstName": "John",
8 "lastName": "Doe",
9 "age": 30,
10 "isVerified": true,
11 "preferences": {
12 "theme": "dark",
13 "notifications": true
14 },
15 "tags": ["developer", "javascript"]
16 }
17 }
18}Common JSON mistakes to avoid:
Converting between JSON strings and JavaScript objects is fundamental to API communication. JavaScript provides built-in methods for this conversion.
JSON.parse() - String to Object:
1// Basic parsing
2const jsonString = '{"name": "John", "age": 30}';
3const user = JSON.parse(jsonString);
4console.log(user.name); // "John"
5console.log(user.age); // 30Safe JSON parsing with error handling:
1function safeJSONParse(jsonString, defaultValue = null) {
2 try {
3 const result = JSON.parse(jsonString);
4 return result;
5 } catch (error) {
6 console.error('JSON parse error:', error.message);
7 return defaultValue;
8 }
9}
10
11// Usage
12const userData = safeJSONParse(apiResponse, {});
13if (!userData.id) {
14 console.log('Failed to parse user data');
15}JSON.stringify() - Object to String:
1const user = {
2 id: 123,
3 name: "John Doe",
4 email: "[email protected]",
5 preferences: {
6 theme: "dark",
7 notifications: true
8 }
9};
10
11// Basic stringification
12const jsonString = JSON.stringify(user);
13
14// Pretty printing with indentation
15const prettyJSON = JSON.stringify(user, null, 2);
16
17// Selective stringification (filter sensitive data)
18const publicJSON = JSON.stringify(user, (key, value) => {
19 if (key === 'password' || key === 'apiKey') {
20 return undefined; // Exclude from output
21 }
22 return value;
23});Handling API responses:
1async function fetchUser(userId) {
2 try {
3 const response = await fetch('/api/users/' + userId);
4
5 if (!response.ok) {
6 throw new Error('HTTP ' + response.status + ': ' + response.statusText);
7 }
8
9 // response.json() is equivalent to JSON.parse(await response.text())
10 const user = await response.json();
11 return user;
12
13 } catch (error) {
14 console.error('Failed to fetch user:', error);
15 throw error;
16 }
17}When working with JSON from external APIs, you cannot assume the data structure will always match your expectations. Implementing robust validation ensures your application remains stable.
Basic data validation:
1function validateUser(userData) {
2 const errors = [];
3
4 // Required fields
5 if (!userData.id || typeof userData.id !== 'number') {
6 errors.push('User ID is required and must be a number');
7 }
8
9 if (!userData.name || typeof userData.name !== 'string') {
10 errors.push('User name is required and must be a string');
11 }
12
13 if (!userData.email || typeof userData.email !== 'string') {
14 errors.push('User email is required and must be a string');
15 }
16
17 // Email format validation
18 if (userData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(userData.email)) {
19 errors.push('User email must be a valid email address');
20 }
21
22 return {
23 isValid: errors.length === 0,
24 errors: errors
25 };
26}Data transformation:
1// Transform API response to application format
2function transformUser(apiUser) {
3 return {
4 id: apiUser.id,
5 fullName: apiUser.first_name + ' ' + apiUser.last_name,
6 email: apiUser.email_address,
7 isActive: apiUser.status === 'active',
8 joinDate: new Date(apiUser.created_at),
9 preferences: {
10 theme: (apiUser.user_preferences && apiUser.user_preferences.ui_theme) || 'light',
11 notifications: (apiUser.user_preferences && apiUser.user_preferences.email_notifications) || false
12 }
13 };
14}
15
16// Transform array of users
17async function fetchTransformedUsers() {
18 const response = await fetch('/api/users');
19 const apiUsers = await response.json();
20 return apiUsers.map(transformUser);
21}Safe property access:
1// Safe property access with default values
2function safeGet(obj, path, defaultValue = null) {
3 const keys = path.split('.');
4 let current = obj;
5
6 for (const key of keys) {
7 if (current === null || current === undefined || !(key in current)) {
8 return defaultValue;
9 }
10 current = current[key];
11 }
12
13 return current;
14}
15
16// Usage
17const userData = await response.json();
18const themeName = safeGet(userData, 'preferences.theme', 'light');
19const street = safeGet(userData, 'address.street', 'Unknown');
20
21// Alternative with optional chaining (modern browsers)
22const theme = userData?.preferences?.theme ?? 'light';
23const userStreet = userData?.address?.street ?? 'Unknown';Array data processing:
1// Group data by property
2function groupBy(array, keyFn) {
3 return array.reduce((groups, item) => {
4 const key = keyFn(item);
5 if (!groups[key]) {
6 groups[key] = [];
7 }
8 groups[key].push(item);
9 return groups;
10 }, {});
11}
12
13// Sort data by property
14function sortBy(array, keyFn, direction = 'asc') {
15 return [...array].sort((a, b) => {
16 const aVal = keyFn(a);
17 const bVal = keyFn(b);
18
19 if (direction === 'desc') {
20 return bVal > aVal ? 1 : bVal < aVal ? -1 : 0;
21 }
22 return aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
23 });
24}
25
26// Usage examples
27const orders = await fetch('/api/orders').then(r => r.json());
28
29// Group orders by status
30const ordersByStatus = groupBy(orders, order => order.status);
31
32// Sort by total amount descending
33const topOrders = sortBy(orders, order => order.total, 'desc');Your progress is saved in this browser, on this device only.