Decimal Numbers with .00 Losing Their Trailing Zeros in JavaScript

By Alan Norman

So, a few years back, I hit this annoying roadblock with decimal numbers that had trailing zeros in Node.js. It was one of those sneaky little issues that gobbled up almost an entire day, and I’m hoping my story will save you from banging your head against the wall if you run into the same tiny but frustrating problem.

The Problem: Decimal Numbers with .00 Losing Their Trailing Zeros

In one of my projects, where I was the go-to guy as the Solution Lead, our squad was working on a service that was hooked up to all sorts of financial platforms. These platforms kept firing JSON payloads at us through POST requests, and our Node.js app, running on Express, was in charge of handling them. We were using app.use(express.json()) to break down the incoming JSON data.

Everything was running like a dream until one of our partners started sending JSON with an “amount” key that had those pesky trailing zeros, like “amount”: “10.00”. The issue? JavaScript doesn’t give a damn about the difference between 10.00 and 10 when it’s turning strings into numbers. This blew up in our faces because we needed to whip up a digital signature from the raw request body. If the signature was made from “amount”: “10” instead of “amount”: “10.00”, we were toast—mismatch galore.

The Challenge: Keeping the OG JSON Format Untouched

So, app.use(express.json()) was doing its job a little too well, parsing the JSON and tossing those zeros out the window, leaving us high and dry with no way to grab the raw JSON string. Ripping out app.use(express.json()) wasn’t an option because that would mean blowing up half our code and throwing the SOLID principles we love right out the window.

Our quick-and-dirty hack? We started fudging the amounts by adding tiny values, turning 10.00 into 10.01. It bought us some time to figure things out, but let’s be real—this was a band-aid at best, especially in the finance world where precision is king.

The Fix: Using the verify Option in express.json()

After digging around a bit, I stumbled on the fact that the fix was actually stupid simple. Express has this cool verify option in the express.json() method that lets you grab the raw request body before it gets all chopped up into JSON.

Here’s how you can make it work:

app.use(express.json({
  verify: (req, _, buf) => req.rawBody = Buffer.from(buf).toString()
}));

The verify function kicks in before the body gets turned into JSON. This lets you stash the raw body as a string, making sure that “amount”: “10.00” stays just like it is. Then, you can grab both the parsed JSON and the raw string in your controllers:

const { body, rawBody } = req;
// body - JSON-parsed output
// rawBody - Original raw string received before parsing

Heads Up: Tread Carefully When Tweaking the req Object

Now, I gotta warn you, tweaking the req object isn’t exactly textbook practice, but sometimes you gotta bend the rules to fit your setup. The main takeaway is that you can keep both the raw and parsed versions of the JSON body in one neat package.

Looking back, the fix was right under my nose, but when you’re in the thick of it, even seasoned devs can miss the easy stuff. Hopefully, this saves someone out there from going through the same hassle. Remember, knowing the ins and outs of your tools can often turn what seems like a huge problem into a quick fix.

Happy coding, peeps!