I have a tail recursive function whose purpose is to find any number
in any number of nested objects
and simply run the toFixed()
on it.
The function formatData() works by looping through the object
, testing to see what type of value is the current iteration is on, performing a function(toFixed()) on said iteration and saving it in a new object or do nothing and just saving the value as is. The end result will be a an identical object but with any long decimal place numbers trimmed to two decimal places.
During testing I've found that if there is a null
value in the object
at any level, it is first saved as null
but later ends up being an object
. I'm aware that in JS null
is considered of type object
and the typeof
keyword will show this.
Here is a codepen of the problem: https://codepen.io/Danny_Wobble/pen/YzqMzxw
Please note that the third console entry shows the value being correctly assigned/saved as null
. Later on as described it ends up as an object
.
Function:
function formatData(data) {
const formattedData = {}
for (const key in data) {
if (data[key] === null) formattedData[key] = null
// if (data[key] === null) formattedData[key] = 'null' // have tried saving as diff val, didn't work
if (data[key] === false) formattedData[key] = false
if (typeof data[key] === 'number') formattedData[key] = data[key].toFixed(2)
if (typeof data[key] === 'object') formattedData[key] = formatData(data[key]) // tail recursion
}
return formattedData
}
Given:
const data = {
status: false,
survey: {
2018: 3.4288,
2019: 3.47701,
2020: null,
},
benchmarks: {
company: 3.455,
industry: 3.5,
portfolio: 3.4,
},
}
const formattedData = formatData(data)
Expectation (formattedData):
{
"status": false,
"survey": {
"2018": "3.43",
"2019": "3.48",
"2020": null,
},
"benchmarks": {
"company": "3.50",
"industry": "3.50",
"portfolio": "3.40",
},
}
Actual result (formattedData):
{
"status": false,
"survey": {
"2018": "3.43",
"2019": "3.48",
"2020": {} // this should be `null`
},
"benchmarks": {
"company": "3.50",
"industry": "3.50",
"portfolio": "3.40"
}
}
You need to exclude null
values from the object check.
if (data[key] && typeof data[key] === 'object')
// ^^^^^^^^^^^^
You could change the logic for checking only the values for different processing, like numbers and objects and continue
or just assign the given value to the new object.
function formatData(data) {
const formattedData = {}
for (const key in data) {
if (typeof data[key] === 'number') {
formattedData[key] = data[key].toFixed(2)
continue;
}
if (data[key] && typeof data[key] === 'object') {
formattedData[key] = formatData(data[key]);
continue;
}
formattedData[key] = data[key];
}
return formattedData;
}
const
data = {
status: false,
survey: {
2018: 3.4288,
2019: 3.47701,
2020: null
},
benchmarks: {
company: 3.455,
industry: 3.5,
portfolio: 3.4
}
},
formattedData = formatData(data);
console.log(formattedData);