JAVASCRIPT
Mapping Complex API Responses to Simple Data Models
Learn to transform verbose or inconsistently structured API response data into a clean, consistent, and easy-to-use local data model in JavaScript for better application maintainability.
/**
* Represents a simplified user profile for the application.
* @typedef {object} UserProfile
* @property {string} id - Unique user identifier.
* @property {string} fullName - User's first and last name combined.
* @property {string} emailAddress - User's email.
* @property {string} avatarUrl - URL to the user's avatar image.
* @property {boolean} isActive - Whether the user account is active.
* @property {string} registrationDate - Date of user registration in ISO format.
*/
/**
* Transforms a complex API user response into a simplified UserProfile object.
* This function handles various naming conventions, nested objects, and data types.
* @param {object} apiUserData - The raw user data object from the API.
* @returns {UserProfile|null} A simplified UserProfile object, or null if essential data is missing.
*/
function transformApiUserToUserProfile(apiUserData) {
if (!apiUserData || !apiUserData.userId || !apiUserData.contactInfo?.email) {
console.warn('Incomplete API user data provided for transformation.', apiUserData);
return null;
}
const firstName = apiUserData.personalDetails?.firstName || apiUserData.fName || '';
const lastName = apiUserData.personalDetails?.lastName || apiUserData.lName || '';
const fullName = `${firstName} ${lastName}`.trim();
return {
id: String(apiUserData.userId), // Ensure ID is a string
fullName: fullName || 'N/A',
emailAddress: apiUserData.contactInfo.email,
avatarUrl: apiUserData.profile?.imageLink || 'https://example.com/default-avatar.png',
isActive: apiUserData.accountStatus === 'active', // Map string status to boolean
registrationDate: new Date(apiUserData.createdAt || apiUserData.registeredAt).toISOString(),
};
}
// Example API Response Structure:
// const complexApiUserData = {
// userId: 12345,
// personalDetails: {
// firstName: 'John',
// lastName: 'Doe',
// dateOfBirth: '1990-05-15'
// },
// contactInfo: {
// email: '[email protected]',
// phone: '+1-555-123-4567'
// },
// profile: {
// imageLink: 'https://example.com/avatars/john.jpg',
// bio: 'Software Developer'
// },
// accountStatus: 'active',
// createdAt: '2020-01-01T10:00:00Z',
// preferences: {
// theme: 'dark'
// }
// };
// Another example with slightly different fields:
// const alternativeApiUserData = {
// userId: 'UUID-67890',
// fName: 'Jane',
// lName: 'Smith',
// contactInfo: {
// email: '[email protected]',
// phone: '+1-555-987-6543'
// },
// profile: { /* no imageLink */ },
// accountStatus: 'inactive',
// registeredAt: '2021-03-10T14:30:00Z'
// };
// const transformedUser = transformApiUserToUserProfile(complexApiUserData);
// console.log('Transformed User 1:', transformedUser);
/* Expected output:
{
id: '12345',
fullName: 'John Doe',
emailAddress: '[email protected]',
avatarUrl: 'https://example.com/avatars/john.jpg',
isActive: true,
registrationDate: '2020-01-01T10:00:00.000Z'
}
*/
// const transformedUser2 = transformApiUserToUserProfile(alternativeApiUserData);
// console.log('Transformed User 2:', transformedUser2);
/* Expected output:
{
id: 'UUID-67890',
fullName: 'Jane Smith',
emailAddress: '[email protected]',
avatarUrl: 'https://example.com/default-avatar.png',
isActive: false,
registrationDate: '2021-03-10T14:30:00.000Z'
}
*/
// const incompleteUser = transformApiUserToUserProfile({ userId: 123 }); // Returns null
// console.log('Incomplete User:', incompleteUser);
How it works: This JavaScript snippet demonstrates a common practice in API integration: transforming raw, potentially complex or inconsistent API response data into a clean, predefined local data model. The `transformApiUserToUserProfile` function specifically maps various fields from an `apiUserData` object (handling nested properties, different naming conventions, and default values) into a simpler `UserProfile` structure. This approach centralizes data normalization, making application code that consumes this data more readable, maintainable, and resilient to changes in the external API's structure.