Capstone: JSON numbers that arrive as strings
This report has been right for months. This morning it mailed a customer an
invoice whose total reads $19.9925.508.99. Nothing threw. No error, no
alert - the total simply walked into a PDF and out to a human.
One line item changed. MS-204 now comes from a supplier whose serializer
writes decimals as JSON strings ("25.50") rather than numbers, which real
payment APIs genuinely do - a string cannot lose precision the way a float can.
The other two lines still arrive as numbers. JSON.parse hands all three back
exactly as written, because parsing is not validating: JSON has both types, and
nothing in the format promises you which one you will get.
Then + decides. In JavaScript + is two operators sharing one symbol: add
these numbers, or join these strings. If either side is a string, joining wins.
So the reduce runs 0 + 19.99 and gets 19.99, then 19.99 + "25.50" and gets
"19.9925.50", then joins 8.99 onto the end of that. Every step is legal.
Every step is silent.
Number("25.50") gives you 25.5 and fixes it - but only halfway. Number("n/a")
gives NaN, and NaN spreads through arithmetic just as quietly: sum + NaN is
NaN, from there to the end, without a word. Coercing alone trades one silent
wrong answer for another. So you coerce and check, at the edge where the data
comes in - which turns a bad amount into a loud error you can locate, instead of
a total nobody thinks to question.
Your task: fix invoiceTotal(json) so it returns the real total as a
number, whatever mix of numbers and numeric strings the lines arrive in. If a
line's amount is not a number at all, throw instead of returning a nonsense
total. The sample payload is already in the editor - its true total is
54.48.
You'll practice:
Coercing and validating untrusted JSON at the boundary instead of trusting its types
Using typeof to prove a total became a string, because + joins the moment either side is one
Show a hint
Show solution
Previous