Reputation: 45
I'm relatively new to JavaScript so please forgive me if this is silly/impossible, but I'm trying to standardize names of properties within a JavaScript object. For example, I have code such as
var object = {
"firstName": "Joe",
"MiddleName": "Roy",
"last_name": "Fool"
}
I want to make a new object that has property names firstName, middleName, and lastName. Is there any way to search through these properties and see which ones are in violation? Otherwise, I could always just make a total copy but that would be quite inefficient. Thanks
Upvotes: 3
Views: 127
Reputation: 1771
This might be going beyond what you're looking for, but it's pretty easy to convert your underscore-separated naming to camelcase; you can iterate over your object and produce a new object with the correct names:
var converter = /_(\w)/g, lowerFirst = /^(\w)/;
function convertName(name) {
if (converter.test(name)) {
name = name.toLowerCase().replace(converter, function ($0, $1) {
return $1.toUpperCase();
});
} else {
// correct a first letter being uppercase
name = name.replace(lowerFirst, function ($0, $1){ return $1.toLowerCase(); });
}
return name;
}
var hasOwnProperty = Object.prototype.hasOwnProperty,
toString = Object.prototype.toString;
function isPlainObject(obj) {
return toString.call(obj) === '[object Object]';
}
function convertObject(obj) {
var k, output = {};
for(k in obj) {
if (hasOwnProperty.call(obj, k)) {
output[convertName(k)] = isPlainObject(obj[k]) ? convertObject(obj[k]) : obj[k];
}
}
return output;
}
If the property names are already in camelcase, they won't be changed by the regexp.
Upvotes: 1
Reputation: 23472
You could possibly do something like this.
The first replace
can be used to replace any characters that you want to be markers for upper cased camel casing.
The second replace
performs the camel casing on the letter that follows the marker.
The final replace
makes sure that the first letter of the identifier is lower case.
standardiseProperties
works on the object
in place using the rules of camelCase
. But you could just as well have it return the new object standardised
.
If a name can not be used as it already exists, then the original name is used.
I didn't spend much time on this and there could well be optimisations, or you may wish to change the rules somewhat.
Javascript
function camelCase(string) {
return string.replace(/[-+]/g, "_").replace(/_([\da-z])/gi, function (all, letter) {
return letter.toUpperCase();
}).replace(/^([A-Z])/, function (all, letter) {
return letter.toLowerCase();
});
}
function standardiseProperties(object) {
var standardised = {},
newName,
i;
for (i in object) {
if (object.hasOwnProperty(i)) {
newName = camelCase(i);
if (standardised.hasOwnProperty(newName)) {
standardised[i] = object[i];
} else {
standardised[newName] = object[i];
}
delete object[i];
}
}
for (i in standardised) {
object[i] = standardised[i];
}
}
var object = {
"firstName": "Joe",
"MiddleName": "Roy",
"last_name": "Fool"
};
console.log(object);
standardiseProperties(object);
console.log(object);
Output
Object {firstName: "Joe", MiddleName: "Roy", last_name: "Fool"}
Object {firstName: "Joe", middleName: "Roy", lastName: "Fool"}
On jsfiddle
Upvotes: 0
Reputation: 66324
By your example, one quick way is to map values of properties to a second object with a dictionary to choose the property names, obtained by (for example) Object.getOwnPropertyNames
var object = {"firstName": "Joe", "MiddleName": "Roy", "last_name": "Fool"};
var p = Object.getOwnPropertyNames(object), // ["firstName", "MiddleName", "last_name"]
dict = {
'firstname': 'firstName',
'first_name': 'firstName',
'middlename': 'middleName',
'middle_name': 'middleName',
'lastname': 'lastName',
'last_name': 'lastName'
},
o2 = {}, i;
for (i = 0; i < p.length; ++i) {
o2[dict[p[i].toLowerCase()] || p[i]] = object[p[i]];
}
o2; // {firstName: "Joe", middleName: "Roy", lastName: "Fool"}
Upvotes: 0