If you’ve built APIs for any length of time, you’ve probably defaulted to JSON without a second thought.
It’s the lingua franca of the web: easy to read, easy to generate, supported everywhere.
What could possibly be wrong?
Well, like that “free” trial subscription you forgot to cancel, JSON comes with hidden costs that only show up later — usually when your API is under real load, or your data model starts growing.
A Quick History Lesson: XML → JSON → ???
Remember when XML was the default for APIs?
- Verbose tags everywhere
- Endless angle brackets
- Painful parsing
JSON felt like a breath of fresh air — shorter, cleaner, more readable.
But here’s the catch: JSON is also verbose. Maybe not as bad as XML, but once your payloads start growing, you’ll realize it still carries a lot of unnecessary weight.
So, we essentially traded one kind of verbosity for another.
1. Verbosity = Bigger Payloads
Here’s a simple example:
{
"id": 123,
"username": "john_doe",
"isActive": true
}
Looks innocent enough. But as your data model grows, every field name gets repeated, every nested object gets wrapped in braces.
Compare that with a binary format like Protobuf: the same data can be represented in fewer bytes — sometimes 5x smaller.
At scale, verbosity means:
- Higher bandwidth costs
- Slower network transfer
- More time spent parsing large payloads
2. Parsing Overhead
JSON parsing is CPU-intensive compared to binary formats.
A classic example:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
Simple, right? But behind the scenes:
- The parser scans every character.
- Validates structure.
- Maps to strings, numbers, booleans.
- Then builds Java objects.
On a single request, no big deal. On 10k requests per second? Suddenly your CPU is working overtime just to shuffle text into objects.
3. Numbers Are… Tricky
JSON doesn’t distinguish between integer sizes.
-
123
could be anint
,long
, orBigInteger
. -
123.45
might be afloat
,double
, orBigDecimal
.
I once had a production bug where a JSON field holding an order ID (1234567890123456789
) silently lost precision because the client treated it as a double.
Lesson learned: JSON loves ambiguity when it comes to numbers.
4. Dates & Times = Pain
Quick question: how do you represent a date in JSON?
- ISO-8601 string?
- Unix timestamp?
- Custom "MM/dd/yyyy" string?
Every system does it differently.
And the worst part? The JSON spec doesn’t care — it has no native date type.
I’ve spent hours debugging “off by one day” bugs because one service serialized dates in UTC, another in local time, and JSON didn’t give me any hints.
5. Lack of Schema = Surprises
JSON is schema-less, which feels liberating at first… until your client app breaks because someone renamed a field.
Example:
{
"firstName": "John"
}
Becomes:
{
"givenName": "John"
}
Suddenly half your clients are broken — and you won’t even know until the bug reports roll in.
With Protobuf or Avro, schemas are explicit and evolution is safer. With JSON, you’re relying on “be careful, don’t change stuff.”
6. Hidden Security Risks
Attackers love JSON because parsers are everywhere and implementations vary. Some hidden costs:
- JSON bombs: deeply nested objects that crash parsers.
- Injection attacks: improperly escaped values.
- Large payload attacks: abusing verbosity to exhaust memory.
Your “simple JSON parser” is suddenly a new attack surface.
7. Tooling Fatigue
Ever tried to version JSON APIs? Or generate type-safe clients? Or validate large payloads?
It’s possible — but clunky. You end up bolting on tools:
- JSON Schema
- Code generators
- Manual validators
Meanwhile, binary formats come with schemas built-in, and code generation “just works.”
Industry Shift: Even LinkedIn Moved Away
This isn’t just theory.
LinkedIn famously moved away from JSON to Protobuf for their internal APIs. Why?
- Reduced payload size
- Lower CPU cost for parsing
- Strong schema guarantees
When a company operating at LinkedIn’s scale makes that shift, it’s worth paying attention.
So, Should We Abandon JSON?
Not at all. JSON still shines for:
- Human readability (debugging is easy).
- Prototyping (quick and dirty works).
- Interoperability (every language speaks it).
But for high-scale APIs, JSON’s hidden costs add up fast.
My personal rule of thumb:
- JSON for external/public APIs where interoperability matters.
- Protobuf/Avro/MessagePack for internal APIs where efficiency matters.
Closing Thoughts
JSON is like pizza. 🍕
Everybody loves it, it’s everywhere, and it works most of the time.
But if you eat only pizza every day, eventually you’ll regret it.
So next time you’re designing an API, ask yourself:
👉 Do I really need JSON here, or is it time to reach for something faster, safer, leaner?
Top comments (0)