I have this JSON object myFilters:
{"filters":
{"role":"","jobs":[]}
}
I can correctly remove the empty object from it with this function clean (myFilters):
function clean(obj) {
for (var propName in obj) {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
delete obj[propName];
}
}
So now, my myFilters object becomes:
{"filters":
{ "jobs":[] }
}
How can I now remove the empty array and the key from my JSON object?
You should add one more condition like
function clean(obj) {
for (var propName in obj) {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === "" ||
Array.isArray(obj[propName]) && obj[propName].length === 0
) {
delete obj[propName];
}
}
}
You should check the type of property before check its value by the
typeof
The jobs property is an object and you can check its value by its
length. it is empty if its length equals to 0.
function clean(obj) {
for (var propName in obj) {
if (typeof (obj[propName]) == 'object') {
if (obj[propName].length == 0) {
delete obj[propName];
}
} else {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
delete obj[propName];
}
}
}
}
I like Saveli Tomac's solution, so I upvoted that. Let me show you an additional shortening on the original solution also.
As it's been stated that you need to check 2 more things if you are looking for an empty array. So what about checking null, undefined and '' values easier?
if (!undefined) { console.log('undefined needs to be deleted') };
if (!null) { console.log('null needs to be deleted') };
if (!'') { console.log(`'' needs to be deleted`) };
Checking Array.length if it has 0 value can be also shorter just like the following:
const array1 = [];
const array2 = [1,2,3];
if (!array1.length) { console.log('array1 has 0 length') };
if (!array2.length) { console.log('array2 has 0 length') };
So based on those code snippets you can have an additional shortening just like the following:
// extended with other types for the demo
let myObject = { "filters": { "role": "", "jobs": [], "nullValue": null, "undefinedIsHere": undefined, "arrayWithValue": [1,2,3], "stringValue": "hello", "numberishere": 123 } };
const clean = (obj) => {
for (let propName in obj) {
if (
!obj[propName] ||
Array.isArray(obj[propName]) && !obj[propName].length
) { delete obj[propName] };
}
}
clean(myObject.filters);
console.log(myObject);
Or with a 1️⃣ liner:
// extended with other types for the demo
let myObject = { "filters": { "role": "", "jobs": [], "nullValue": null, "undefinedIsHere": undefined, "arrayWithValue": [1,2,3], "stringValue": "hello", "numberishere": 123 } };
const clean = (obj) => {
Object.keys(obj).forEach(propName => (!obj[propName] || Array.isArray(obj[propName]) && !obj[propName].length) && delete obj[propName]);
}
clean(myObject.filters);
console.log(myObject);
Read further here:
Array.isArray()
Array.length
I hope this helps!
Try this :
var filterObj = {
"filters": {
"role": "",
"jobs": []
}
};
for (var i in filterObj) {
for (var j in filterObj[i]) {
if ((filterObj[i][j] === null) ||
(filterObj[i][j] === undefined) ||
(filterObj[i][j].length === 0)) {
delete filterObj[i][j];
}
}
}
console.log(filterObj);
Saveli's answer should work fine. Here's an alternative approach you can use to achieve the same result.
const object = {
"filters": {
"role": "",
"jobs": [],
"foo": undefined,
"baz": null,
"bar": {},
"moreJobs": ['1', '2']
}
}
const result = {
filters: Object.keys(object.filters).reduce((acc, key) => {
if (
object.filters[key] !== null &&
object.filters[key] !== undefined &&
object.filters[key] !== '' &&
typeof object.filters[key] === 'object' && Object.keys(object.filters[key]).length > 0
) {
acc[key] = object.filters[key];
}
return acc;
}, {})
};
console.log(result);
It should be like this:
function clean(obj) {
for (var propName in obj) {
if (obj.hasOwnProperty(propName) &&
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === "" ||
(Array.isArray(obj[propName]) && obj[propName].length <= 0)
) {
delete obj[propName];
}
}
}
Related
The following code prints the path of the key searched by its value inside an object:
function findKeyPath(obj, keyAttr, keyValue) {
let path = "";
(function findKey (obj, keyAttr, keyValue, keyPath) {
const prevPath = `${keyPath ? keyPath + "." : ""}`;
if (obj[keyAttr] === keyValue) {
path = `${prevPath}${keyAttr}`;
} else if (typeof obj === "object" && JSON.stringify(obj) === JSON.stringify(keyValue)) {
path = prevPath.slice(0, -1); // remove last dot
}
if (typeof obj === "object" && !Array.isArray(obj)) {
for (const key in obj) {
if (Array.isArray(obj[key])) {
for (let j = 0; j < obj[key].length; j++) {
findKey(obj[key][j], keyAttr, keyValue, `${prevPath}${key}[${j}]`);
}
}
if (obj[key] !== null && typeof obj[key] === "object") {
findKey(obj[key], keyAttr, keyValue, `${prevPath}${key}`);
}
}
}
}(obj, keyAttr, keyValue));
return path;
}
console.log(
findKeyPath({
users: [
{ name: "sam", surname: "red", age: 12 },
{ name: "sam", surname: "red", age: 42 },
{ name: "sam", surname: "red", age: 16 }
]
}, "age", 16)
);
... it prints users[2].age.
Trying to taking out the inner function, like this:
function findKey(obj, keyAttr, keyValue, keyPath) {
const prevPath = `${keyPath ? keyPath + "." : ""}`;
if (obj[keyAttr] === keyValue) {
return `${prevPath}${keyAttr}`;
} else if (typeof obj === "object" && JSON.stringify(obj) === JSON.stringify(keyValue)) {
return prevPath.slice(0, -1); // remove last dot
}
if (typeof obj === "object" && !Array.isArray(obj)) {
for (const key in obj) {
if (Array.isArray(obj[key])) {
for (let j = 0; j < obj[key].length; j++) {
findKey(obj[key][j], keyAttr, keyValue, `${prevPath}${key}[${j}]`);
}
}
if (obj[key] !== null && typeof obj[key] === "object") {
findKey(obj[key], keyAttr, keyValue, `${prevPath}${key}`);
}
}
}
}
console.log(
findKey({
users: [
{ name: "sam", surname: "red", age: 12 },
{ name: "sam", surname: "red", age: 42 },
{ name: "sam", surname: "red", age: 16 }
]
}, "age", 16)
);
It prints undefined. How can I solve it?
UPDATE, now it works:
function findKey(obj, keyAttr, keyValue, keyPath) {
const prevPath = `${keyPath ? keyPath + "." : ""}`;
let path = "";
if (obj[keyAttr] === keyValue) {
return `${prevPath}${keyAttr}`;
} else if (typeof obj === "object" && JSON.stringify(obj) === JSON.stringify(keyValue)) {
return prevPath.slice(0, -1); // remove last dot
}
if (typeof obj === "object" && !Array.isArray(obj)) {
for (const key in obj) {
if (Array.isArray(obj[key])) {
for (let j = 0; j < obj[key].length; j++) {
path = path.concat(findKey(obj[key][j], keyAttr, keyValue, `${prevPath}${key}[${j}]`));
}
}
if (obj[key] !== null && typeof obj[key] === "object") {
return path.concat(findKey(obj[key], keyAttr, keyValue, `${prevPath}${key}`));
}
}
}
return path;
}
One problem with second code snippet I can think of is, we have path as a variable who is getting updated throughout the findKey function calls, it is a sort of "protected variable" which the findKey function can access and modify. In second code snippet we are not modifying the variable but returning it directly to the caller, which might not return anything for this part of code
if (typeof obj === "object" && !Array.isArray(obj)) {
for (const key in obj) {
if (Array.isArray(obj[key])) {
for (let j = 0; j < obj[key].length; j++) {
findKey(obj[key][j], keyAttr, keyValue, `${prevPath}${key}[${j}]`);
}
}
if (obj[key] !== null && typeof obj[key] === "object") {
findKey(obj[key], keyAttr, keyValue, `${prevPath}${key}`);
}
}
Imagine findKey getting called here and returning things as per your expectation but then we are not returning anything from this function, hence the undefined is getting returned. We might need to introduce a variable and store results and return it for this part of code.
I have created a function to recursively find empty values in a nested array.
The function returns the correct value at first but seems to reset it to the input value before returning the result.
What am I missing?
Here is my code:
const obj = [
{
mainContact: true,
contactName: "",
emailId: "abc#gmail.com",
contactAddress: [
{
addressType: "",
county: "U.K.",
postCode: "MK7 6BZ",
houseFlatNumber: 1
},
{
addressType: "def",
county: "France",
postCode: "123MKO",
houseFlatNumber: "223"
}
],
phoneDetails: [
{
notes: "",
phoneNumber: "1234567899",
countryCode: "44",
priority: "1"
},
{
notes: "Lorem ipsum",
phoneNumber: "1112223331",
countryCode: "48",
priority: "2"
}
]
}
];
function validObject(obj, isOk) {
for (var propName in obj) {
if (typeof obj[propName] === "object") {
this.validObject(obj[propName], isOk);
} else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
isOk = false;
break;
}
}
return isOk;
}
console.log(validObject(obj), true);
// This should return false but it returns true although it first hit the return isOk line
// with a false value then set it back to true
Any help would be much appreciated.
Thanks.
The thing about recursion is that you have to return the value from your recursive call. That means that you call the function from inside itself, then handle the return value accordingly.
Here's my interpretation of your function, where I add a simple base case to check if the passed value is null, undefined, or empty string.
function isValidObject(obj) {
// Base case
if (obj[propName] === null || obj[propName] === undefined || obj[propName] === '') {
return false;
}
// Recurse through each item in object
if (typeof obj === "object") {
for (var propName in obj) {
if (!isValidObject(obj[propName]) {
return false;
}
}
}
return true;
}
Notice that this allows you to get rid of the boolean parameter that you pass into your function and instead just return false when the first is found.
The basic issue is that you are not returning the value of the recursion call. So what you are actually doing is performing an inline recursive loop, then returning the value from the parent call.
Also, because isOk is a primitive boolean, it is pass by value rather than pass by reference. Thus modifying isOk inside a child function call doesn't modify the variable in the parent scope.
NOTE: this doesn't apply to obj[propName] (which is pass by reference), so any modifications to the data inside the function will get persisted outside the function.
function validObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( validObject(obj[propName]) === false ) {
// This will propergate back through the call stack
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false; // we don't need a variable here
}
}
return true; // calculatus eliminatus, nothing is false, so it must be true
}
An alternate approach is to write a more generic function to recursively test validity of object properties given a predicate to test with.
It's not difficult; to my mind it's often simpler than writing the specific function directly. And applying it to a specific case is also simple.
It might look like this:
const isValid = (pred) => (obj) =>
Object .values (obj) .every (
v => (v && typeof v == 'object') ? isValid (pred) (v) : pred (v)
)
const noEmptyProps = isValid (v => v !== '' && v != null)
const obj = [{mainContact: true, contactName: "", emailId: "abc#gmail.com", contactAddress: [{addressType: "", county: "U.K.", postCode: "MK7 6BZ", houseFlatNumber: 1}, {addressType: "def", county: "France", postCode: "123MKO", houseFlatNumber: "223"}], phoneDetails: [{notes: "", phoneNumber: "1234567899", countryCode: "44", priority: "1"}, {notes: "Lorem ipsum", phoneNumber: "1112223331", countryCode: "48", priority: "2"}]}]
console.log (noEmptyProps (obj))
Thanks to James McGuigan, my edited version is as below:
isValidObject(obj) {
for (var propName in obj) {
if( typeof obj[propName] === "object" ) {
if( this.isValidObject(obj[propName]) === false ||
obj[propName] === null ||
obj[propName].length === 0 )
{
return false;
}
}
else if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ''
) {
return false;
}
}
return true;
}
How to Replace null with - using single line in jQuery
For Example
var obj={
"Key1":null,
"key2":"I have null",
"key3":null
}
Expected Output:
var obj={
"Key1":"-",
"key2":"I have null",
"key3":"-"
}
You could use Object.keys and check the value. with a recursive function with a closure over the iterating object.
var iter = o => k => o[k] && typeof o[k] === 'object' && Object.keys(o[k]).forEach(iter(o[k])) || o[k] === null && (o[k] = '-'),
object = { Key1: null, key2: "I have null", key3: { kje: "test", dfasfd: null, demo: "null demo" } };
Object.keys(object).forEach(iter(object));
console.log(object);
which basically resolves with ES5 in
var object = { Key1: null, key2: "I have null", key3: { kje: "test", dfasfd: null, demo: "null demo" } };
Object.keys(object).forEach(function iter(o) {
return function (k) {
if (o[k] && typeof o[k] === 'object') {
Object.keys(o[k]).forEach(iter(o[k]));
return;
}
o[k] === null && (o[k] = '-');
};
}(object));
console.log(object);
This one-line function will work:
function nullToDash(obj){for(e in obj){if(obj.hasOwnProperty(e) && obj[e]===null){obj[e]="-";}}}
Edit: Unminified above function for better understanding
function nullToDash(obj){
for(e in obj){
if(obj.hasOwnProperty(e) && obj[e]===null){
obj[e]="-";
}
}
}
In one line, It would look something like
JSON.parse(JSON.stringify(obj).split(":null").join((':\"-"')));
var obj = {
"Key1": null,
"key2": "I have null",
"key3": null
}
var obj1=JSON.parse(JSON.stringify(obj).split(":null").join((':\"-"')));
console.log(obj1)
To make the code generic
$.each( obj, function( key, value ) {
if (value == null)
value = "-";
});
What is the most elegant way to determine if all attributes in a javascript object are either null or the empty string? It should work for an arbitrary number of attributes.
{'a':null, 'b':''} //should return true for this object
{'a':1, 'b':''} //should return false for this object
{'a':0, 'b':1} //should return false
{'a':'', 'b':''} //should return true
Check all values with Object.values. It returns an array with the values, which you can check with Array.prototype.every or Array.prototype.some:
const isEmpty = Object.values(object).every(x => x === null || x === '');
const isEmpty = !Object.values(object).some(x => x !== null && x !== '');
Create a function to loop and check:
function checkProperties(obj) {
for (var key in obj) {
if (obj[key] !== null && obj[key] != "")
return false;
}
return true;
}
var obj = {
x: null,
y: "",
z: 1
}
checkProperties(obj) //returns false
Here's my version, specifically checking for null and empty strings (would be easier to just check for falsy)
function isEmptyObject(o) {
return Object.keys(o).every(function(x) {
return o[x]===''||o[x]===null; // or just "return o[x];" for falsy values
});
}
let obj = { x: null, y: "hello", z: 1 };
let obj1 = { x: null, y: "", z: 0 };
!Object.values(obj).some(v => v);
// false
!Object.values(obj1).some(v => v);
// true
Using Array.some() and check if the values are not null and not empty is more efficient than using Array.every and check it the other way around.
const isEmpty = !Object.values(object).some(x => (x !== null && x !== ''));
This answer should just make the excellent comment of user abd995 more visible.
Quick and simple solution:
Object.values(object).every(value => !!value);
You can use the Array.reduce prototype on your object's keys.
Assuming that the object is structured as follows:
var obj = {
x: null,
y: "",
z: 1
}
you can use the following instruction to discover if all of it's properties are unset or set to empty string using just one line:
Object.keys(obj).reduce((res, k) => res && !(!!obj[k] || obj[k] === false || !isNaN(parseInt(obj[k]))), true) // returns false
If you want to discover if all of it's properties are set instead you have to remove the negation before the conditions and set the initial result value to true only if the object has keys:
Object.keys(obj).reduce((res, k) => res && (!!obj[k] || obj[k] === false || !isNaN(parseInt(obj[k]))), Object.keys(obj).length > 0) // returns false as well
Based on adeneo's answer, I created a single line condition. Hope it will be helpful to someone.
var test = {
"email": "test#test.com",
"phone": "1234567890",
"name": "Test",
"mobile": "9876543210",
"address": {
"street": "",
"city": "",
"state": "",
"country": "",
"postalcode": "r"
},
"website": "www.test.com"
};
if (Object.keys(test.address).every(function(x) { return test.address[x]===''||test.address[x]===null;}) === false) {
console.log('has something');
} else {
console.log('nothing');
}
You can test it https://jsfiddle.net/4uyue8tk/2/
Just complementing the past answers: they'll work if your object doesn't contain arrays or objects. If it does, you'll need to do a 'deep check'.
So I came up with this solution. It'll evaluate the object as empty if all its values (and values inside values) are undefined, {} or [].
function deepCheckEmptyObject(obj) {
return Object.values(obj).every( value => {
if (value === undefined) return true;
else if ((value instanceof Array || value instanceof Object) && _.isEmpty(value) ) return true;
else if (value instanceof Array && !_.isEmpty(value)) return deepCheckEmptyArray(value);
else if (value instanceof Object && !_.isEmpty(value)) return deepCheckEmptyObject(value);
else return false;
});
}
function deepCheckEmptyArray(array) {
return array.every( value => {
if (value === undefined) return true;
else if ((value instanceof Array || value instanceof Object) && _.isEmpty(value)) return true;
else if (value instanceof Array && !_.isEmpty(value)) return deepCheckEmptyArray(value);
else if (value instanceof Object && !_.isEmpty(value)) return deepCheckEmptyObject(value);
else return false;
});
}
Note it uses Lodash's .isEmpty() to do the heavy work after we 'isolated' a value. Here, Lodash is imported as '_'.
Hope it helps!
Also if you are searching for only values are empty within the object,
Object.values({ key: 0, key2: null, key3: undefined, key4: '' }).some(e => Boolean(e))
// false
Object.values({ key: 0, key2: null, key3: undefined, key4: "hello" }).some(e => Boolean(e))
// true
Object.values({ key: 1, key2: "hello" }).some(e => Boolean(e))
// true
Based on tymeJv's answer =)
function checkProperties(obj) {
var state = true;
for (var key in obj) {
if ( !( obj[key] === null || obj[key] === "" ) ) {
state = false;
break;
}
}
return state;
}
var obj = {
x: null,
y: "",
z: 1
}
checkProperties(obj) //returns false
Hope it helps =)
This will give you all the keys from the object which is empty, undefined and null
Object.keys(obj).filter((k)=> {
if (obj[k] === "" || obj[k]===undefined || obj[k]===null) {
return k;
}
});
Building on top of other answers I would use lodash to check isEmpty on the object, as well as its properties.
const isEmpty = (object) => return _.isEmpty(object) || !Object.values(object).some(x => !_.isEmpty(x))
This skip the function attribute
function checkIsNull(obj){
let isNull=true;
for(let key in obj){
if (obj[key] && typeof obj[key] !== 'function') {
isNull = false;
}
}
return isNull;
}
var objectWithFunctionEmpty={
"name":undefined,
"surname":null,
"fun": function (){ alert('ciao'); }
}
var objectWithFunctionFull={
"name":undefined,
"surname":"bla bla",
"fun": function (){ alert('ciao'); }
}
checkIsNull(objectWithFunctionEmpty); //true
checkIsNull(objectWithFunctionFull); //false
This works with me perfectly:
checkProperties(obj) {
let arr = [];
for (let key in obj) {
arr.push(obj[key] !== undefined && obj[key] !== null && obj[key] !== "");
}
return arr.includes(false);
}
This will return true or false if there is at-least one value is empty or something like that.
You can use Object.values() method to get all the object's values (as an array of object's values) and then check if this array of values contains null or "" values, with the help of _.includes method prvided by lodash library.
const checkObjectProperties = obj => {
const objValues = Object.keys(obj);
if (_.includes(objValues, "") || _.includes(objValues, null)) {
return false;
} else {
return true
}
const incorrectObjProps = { one: null, two: "", three: 78 }
const correctObjProps = { one: "some string" }
checkObjectProperties(incorrectObjProps) // return false
checkObjectProperties(correctObjProps) // return true
}
I'll add my two sense:
Object.values(object).every(value => Boolean(value));
Solution:
function checkValues(obj) {
var objValues = Object.values(obj);
if (objValues.length < 1) return false;
return objValues.every((value) => {
if (value === null) return true;
if (typeof(value) == 'string')
if(!(value || false))
return true;
return false;
});
}
// OR
Object.values( obj ).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
Testing:
checkValues({ a: null, b: '' });
// OR
Object.values({ a: null, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
// Output: true
checkValues({ a: '', b: '' });
// OR
Object.values({ a: '', b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
// Output: true
checkValues({ a: 0, b: '' });
// OR
Object.values({ a: 0, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
checkValues({ a: 0, b: 1 });
// OR
Object.values({ a: 0, b: 1 }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
checkValues({ a: 1, b: '' });
// OR
Object.values({ a: 1, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
How about this?
!Object.values(yourObject).join('')
I get a json response from the server that looks something like this:
{
"Response": {
"FirstName": "John",
"LastName": "Smith",
"NickNames": {
"NameOne": "Johnny",
"NameTwo": "JohnS",
"NameThree": "Smithy"
},
"Success": true,
"Errors": []
}
}
Is there a way I can run this response through a function so that the key of each key value pair would be camelCased?
So the output would look something like:
{
"response": {
"firstName": "John",
"lastName": "Smith",
"nickNames": {
"nameOne": "Johnny",
"nameTwo": "JohnS",
"nameThree": "Smithy"
},
"success": true,
"errors": []
}
}
If someone could point me in the right direction, that'd be great.
Thanks.
You would give JSON.parse a reviver function that assigns values to new properties that are lower-cased.
function toCamelCase(key, value) {
if (value && typeof value === 'object'){
for (var k in value) {
if (/^[A-Z]/.test(k) && Object.hasOwnProperty.call(value, k)) {
value[k.charAt(0).toLowerCase() + k.substring(1)] = value[k];
delete value[k];
}
}
}
return value;
}
var parsed = JSON.parse(myjson, toCamelCase);
More information about how it works in this SO answer.
The approach that user '#I Hate Lazy' suggested - using a 'reviver' function is - the right one. However his function didn't work for me.
Perhaps it is because I'm parsing a JSON array. Also I use Resharper and it complained about a code smell :) ('not all code paths return a value'). So I ended up using a function from another SO issue which did work for me:
function camelCaseReviver(key, value) {
if (value && typeof value === 'object') {
for (var k in value) {
if (/^[A-Z]/.test(k) && Object.hasOwnProperty.call(value, k)) {
value[k.charAt(0).toLowerCase() + k.substring(1)] = value[k];
delete value[k];
}
}
}
return value;
}
Here is a functional recursive (ES6) approach.
function convertKeysToCamelCase(o) {
if (o === null || o === undefined) {
return o;
} else if (Array.isArray(o)) {
return o.map(convertKeysToCamelCase);
}
return typeof o !== 'object' ? o : Object.keys(o).reduce((prev, current) => {
const newKey = `${current[0].toLowerCase()}${current.slice(1)}`;
if (typeof o[current] === 'object') {
prev[newKey] = convertKeysToCamelCase(o[current]);
} else {
prev[newKey] = o[current];
}
return prev;
}, {});
}
// successfully tested input
const o = {
SomeNum: 1,
SomeStr: 'a',
SomeNull: null,
SomeUndefined: undefined,
SomeBoolean: true,
SomeNaN: NaN,
NestedObject: {
SomeSentence: 'A is for apple',
AnotherNested: {
B: 'is for blahblah'
}
},
NumArray: [1, 2, 3, 4],
StringArray: ['a', 'b', 'c'],
BooleanArray: [true, false],
ArrayOfArrays: [[1,2,], ['a','b']],
ObjectArray: [{Foo:'bar'}, {Hello:'world', Nested:{In:'deep'}}],
MixedArray: [1,'a', true, null, undefined, NaN, [{Foo:'bar'}, 'wat']]
}
const output = convertKeysToCamelCase(o);
console.log(output.mixedArray[6][0].foo); // 'bar'
#adamjyee Your solution works except for nested array of integers. A small fix could be:
function convertKeysToCamelCase (o) {
if (o === null) {
return null
} else if (o === undefined) {
return undefined
} else if (typeof o === 'number') {
return o
} else if (Array.isArray(o)) {
return o.map(convertKeysToCamelCase)
}
return Object.keys(o).reduce((prev, current) => {
const newKey = `${current[0].toLowerCase()}${current.slice(1)}`
if (typeof o[current] === 'object') {
prev[newKey] = convertKeysToCamelCase(o[current])
} else {
prev[newKey] = o[current]
}
return prev
}, {})
[Right to comment but lacking comment priviledge :(]
You need to write a recursive function that traverses the tree and returns a new tree where the keys in the objects have been updated. The recursive function would call itself to deal with any sub-objects it encounters.