Whats the best way to map all object properties into a new object format with different property names example:
this is the desired format
const person = {
firstName: 'john',
lastName: 'doe',
houses: [{ housName: 'Kruger' }]
}
and I have these two objects
const person1 = {
prenom: 'john', //this should be mapped to the firstName
nom: 'doe', //this should be mapped to the lastName
houses: [{ house_name: 'Kruger' }]
}
const person2 = {
name: 'john', // this should be mapped to the firstName
familyName: 'doe', // this should be assigned to the lastName
Houses: [{ House_Name: 'Kruger' }]
};
The goals is to make person1 and person2 with all their properties and sub properties look like person.
I HAVE TRIED
export class Person {
@Expose({ name: 'prenom' })
firstName: string;
@Expose({ name: 'nom' })
lastName: string;
}
}
//this should give a formatted version from person1 ==> person
const formatted = plainToClass(person1,Person)
However this would require me to create multiple iterations of Person class which is not convenient if we would like to use this class for typing.
CodePudding user response:
First you need to get all the object
keys and values by Object.entries(obj)
, then on each key we need to turn it from pascal case
to camel case
first we need to turn the string to lower case
then with replace
/_([a-z])/gi
which capture the first letter after the underscore _
, and turn it Upper case
.
str.toLowerCase().replace(/_([a-z])/gi, function (g) { return g[1].toUpperCase(); });
Then reduce the array and covert it back to an object.
const mapToCamelCase = (obj) => {
return Object.entries(obj).reduce((acc, [key,value]) => {
var keyCamelCased = toCamelCase(key)
acc[keyCamelCased] = value
return acc
}, {})
}
const person1 = {
first_name: 'john',
last_name: 'doe',
houses: [{ house_name: 'Kruger' }]
}
const person2 = {
First_Name: 'john',
Last_Name: 'doe',
Houses: [{ House_Name: 'Kruger' }]
};
const toCamelCase = (str) => {
return str.toLowerCase().replace(/_([a-z])/gi, function (g) { return g[1].toUpperCase(); });
}
const mapToCamelCase = (obj) => {
return Object.entries(obj).reduce((acc, [key,value]) => {
var keyCamelCased = toCamelCase(key)
acc[keyCamelCased] = value
return acc
}, {})
}
console.log(mapToCamelCase(person1))
console.log(mapToCamelCase(person2))
CodePudding user response:
A simple recursive function can do the name conversion you want. This will work for input with any depth of entries in it.
Using Object.entries() and Object.fromEntries()
const person1 = { first_name: "john", last_name: "doe", houses: [{ house_name: "Kruger" }], }; const person2 = { First_Name: "john", Last_Name: "doe", Houses: [{ House_Name: "Kruger" }], }; const person3 = { first_name: "john", last_name: "doe", houses: [ { house_name: "Kruger", phone_numbers: [{ ext_code: " 54", phone_number: 232242323 }], }, ], };
const formatName = (str) => {
return str
.split("_")
.map(
(w, index) =>
(index > 0 ? w[0].toUpperCase() : w[0].toLowerCase()) w.substring(1)
)
.join("");
};
const formatNames = (input) => {
if (Array.isArray(input)) {
return input.map((item) => formatNames(item));
} else if (typeof input === "object") {
return Object.fromEntries(
Object.entries(input).map(([key, value]) => [
formatName(key),
formatNames(value),
])
);
}
return input;
};
console.log(formatNames(person1));
console.log(formatNames(person2));
console.log(formatNames(person3));
Note: If you made formatName
function an argument to formatNames
then formatNames
is much more flexible as it can be used to form differently name-formatted objects.
CodePudding user response:
My workaround will be creating a class file something like this
in person.js
class Person {
constructor(personObj) {
this.firstName = personObj.first_name,
this.lastName = personObj.Last_Name,
this.houses = personObj.Houses;
}
}
const person1 = {
first_name: 'john',
last_name: 'doe',
houses: [{ house_name: 'Kruger' }]
}
const formatted = new Person(person1)