flattenObject()
Flatten nested objects into dot notation keys for easier access and manipulation.
Utility Function
Objects
Transformation
Syntax
flattenObject(obj, options)Parameters
obj Object
The nested object to flatten.
options object optional
Configuration options.
separator- Key separator (default: '.')maxDepth- Maximum depth to flatten (default: Infinity)includeArrays- Flatten arrays as well (default: false)prefix- Prefix for all keys (default: '')
Returns
Object
- Flattened object with dot notation keys.Examples
Basic Object Flattening
const nested = {
user: {
name: "John",
profile: {
age: 30,
address: {
street: "123 Main St",
city: "New York"
}
}
},
settings: {
theme: "dark",
notifications: true
}
};
const flattened = flattenObject(nested);
console.log(flattened);
// {
// "user.name": "John",
// "user.profile.age": 30,
// "user.profile.address.street": "123 Main St",
// "user.profile.address.city": "New York",
// "settings.theme": "dark",
// "settings.notifications": true
// }Custom Separator
const config = {
database: {
host: "localhost",
credentials: {
username: "admin",
password: "secret"
}
}
};
// Use underscore separator
const flattened = flattenObject(config, { separator: '_' });
console.log(flattened);
// {
// "database_host": "localhost",
// "database_credentials_username": "admin",
// "database_credentials_password": "secret"
// }
// Use slash separator for path-like keys
const pathFlattened = flattenObject(config, { separator: '/' });
console.log(pathFlattened);
// {
// "database/host": "localhost",
// "database/credentials/username": "admin",
// "database/credentials/password": "secret"
// }Depth Control
const deepObject = {
level1: {
level2: {
level3: {
level4: {
value: "deep"
}
}
}
}
};
// Limit flattening depth
const shallowFlattened = flattenObject(deepObject, { maxDepth: 2 });
console.log(shallowFlattened);
// {
// "level1.level2": {
// level3: {
// level4: {
// value: "deep"
// }
// }
// }
// }
// Full depth flattening
const fullFlattened = flattenObject(deepObject);
console.log(fullFlattened);
// {
// "level1.level2.level3.level4.value": "deep"
// }Array Handling
const withArrays = {
users: [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 }
],
tags: ["javascript", "nodejs"],
metadata: {
counts: [1, 2, 3],
info: {
total: 6
}
}
};
// Default: arrays are not flattened
const defaultFlattened = flattenObject(withArrays);
console.log(defaultFlattened);
// {
// "users": [{ name: "Alice", age: 25 }, { name: "Bob", age: 30 }],
// "tags": ["javascript", "nodejs"],
// "metadata.counts": [1, 2, 3],
// "metadata.info.total": 6
// }
// Include arrays in flattening
const arrayFlattened = flattenObject(withArrays, { includeArrays: true });
console.log(arrayFlattened);
// {
// "users.0.name": "Alice",
// "users.0.age": 25,
// "users.1.name": "Bob",
// "users.1.age": 30,
// "tags.0": "javascript",
// "tags.1": "nodejs",
// "metadata.counts.0": 1,
// "metadata.counts.1": 2,
// "metadata.counts.2": 3,
// "metadata.info.total": 6
// }With Prefix
const appConfig = {
api: {
baseUrl: "https://api.example.com",
timeout: 5000
},
ui: {
theme: "dark",
language: "en"
}
};
const flattened = flattenObject(appConfig, { prefix: 'APP_' });
console.log(flattened);
// {
// "APP_api.baseUrl": "https://api.example.com",
// "APP_api.timeout": 5000,
// "APP_ui.theme": "dark",
// "APP_ui.language": "en"
// }Environment Variables Generation
// Convert config to environment variables
const config = {
database: {
host: "localhost",
port: 5432,
ssl: {
enabled: true,
cert: "/path/to/cert"
}
},
redis: {
host: "localhost",
port: 6379
}
};
function configToEnvVars(config) {
const flattened = flattenObject(config, {
separator: '_',
prefix: 'APP_'
});
// Convert to uppercase and format for .env file
const envVars = {};
for (const [key, value] of Object.entries(flattened)) {
const envKey = key.toUpperCase();
envVars[envKey] = typeof value === 'string' ? value : JSON.stringify(value);
}
return envVars;
}
const envVars = configToEnvVars(config);
console.log(envVars);
// {
// "APP_DATABASE_HOST": "localhost",
// "APP_DATABASE_PORT": "5432",
// "APP_DATABASE_SSL_ENABLED": "true",
// "APP_DATABASE_SSL_CERT": "/path/to/cert",
// "APP_REDIS_HOST": "localhost",
// "APP_REDIS_PORT": "6379"
// }
// Generate .env file content
function generateEnvFile(envVars) {
return Object.entries(envVars)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
}
console.log(generateEnvFile(envVars));
// APP_DATABASE_HOST=localhost
// APP_DATABASE_PORT=5432
// APP_DATABASE_SSL_ENABLED=true
// APP_DATABASE_SSL_CERT=/path/to/cert
// APP_REDIS_HOST=localhost
// APP_REDIS_PORT=6379Form Data Processing
// Process nested form data
const formData = {
personal: {
firstName: "John",
lastName: "Doe",
contact: {
email: "john@example.com",
phone: {
home: "555-1234",
mobile: "555-5678"
}
}
},
preferences: {
newsletter: true,
notifications: {
email: true,
sms: false
}
}
};
class FormProcessor {
static flatten(data) {
return flattenObject(data);
}
static validate(flatData) {
const errors = {};
// Validate email
if (flatData['personal.contact.email'] &&
!flatData['personal.contact.email'].includes('@')) {
errors['personal.contact.email'] = 'Invalid email format';
}
// Validate phone numbers
const phonePattern = /^\d{3}-\d{4}$/;
if (flatData['personal.contact.phone.home'] &&
!phonePattern.test(flatData['personal.contact.phone.home'])) {
errors['personal.contact.phone.home'] = 'Invalid phone format';
}
return errors;
}
static process(formData) {
const flattened = this.flatten(formData);
const errors = this.validate(flattened);
return {
flattened,
errors,
isValid: Object.keys(errors).length === 0
};
}
}
const result = FormProcessor.process(formData);
console.log(result.flattened);
// {
// "personal.firstName": "John",
// "personal.lastName": "Doe",
// "personal.contact.email": "john@example.com",
// "personal.contact.phone.home": "555-1234",
// "personal.contact.phone.mobile": "555-5678",
// "preferences.newsletter": true,
// "preferences.notifications.email": true,
// "preferences.notifications.sms": false
// }Configuration Search and Filter
// Search through complex configuration
const appSettings = {
features: {
authentication: {
oauth: {
google: { enabled: true, clientId: "google123" },
github: { enabled: false, clientId: "github456" }
},
local: { enabled: true, minPasswordLength: 8 }
},
payments: {
stripe: { enabled: true, publicKey: "pk_test_123" },
paypal: { enabled: false, clientId: "paypal789" }
}
},
ui: {
theme: {
default: "light",
options: ["light", "dark", "auto"]
}
}
};
class ConfigSearch {
constructor(config) {
this.flattened = flattenObject(config);
}
search(query) {
const results = {};
const lowerQuery = query.toLowerCase();
for (const [key, value] of Object.entries(this.flattened)) {
if (key.toLowerCase().includes(lowerQuery) ||
String(value).toLowerCase().includes(lowerQuery)) {
results[key] = value;
}
}
return results;
}
getByPattern(pattern) {
const results = {};
const regex = new RegExp(pattern);
for (const [key, value] of Object.entries(this.flattened)) {
if (regex.test(key)) {
results[key] = value;
}
}
return results;
}
getEnabled() {
return this.getByPattern('\.enabled$');
}
getCredentials() {
return this.getByPattern('(clientId|publicKey|secretKey)$');
}
}
const configSearch = new ConfigSearch(appSettings);
// Search for "google" related settings
console.log(configSearch.search('google'));
// {
// "features.authentication.oauth.google.enabled": true,
// "features.authentication.oauth.google.clientId": "google123"
// }
// Get all enabled features
console.log(configSearch.getEnabled());
// {
// "features.authentication.oauth.google.enabled": true,
// "features.authentication.oauth.github.enabled": false,
// "features.authentication.local.enabled": true,
// "features.payments.stripe.enabled": true,
// "features.payments.paypal.enabled": false
// }
// Get all credentials
console.log(configSearch.getCredentials());
// {
// "features.authentication.oauth.google.clientId": "google123",
// "features.authentication.oauth.github.clientId": "github456",
// "features.payments.stripe.publicKey": "pk_test_123",
// "features.payments.paypal.clientId": "paypal789"
// }