We've all been there: It's Friday at 4:55 PM. You just need to merge two simple .json config files for deployment.
"This will take 30 seconds," you whisper — a naive lie to yourself.
Flash forward 3 hours later: You're staring blankly at a screen full of missing commas, silently questioning your life choices. 💀
Here is the tragic 3-act story of every developer who has ever tried to merge JSON files by hand.
Act I: "I'll just use Object.assign()!"
You open config.old.json and config.new.json. You want to update an endpoint while keeping your default timeout settings.
const target = { api: { endpoint: "/v1", timeout: 5000 }, features: { darkmode: true } }; const source = { api: { endpoint: "/v2" } // missing timeout! }; // Shallow merge using Object.assign(): const result = Object.assign({}, target, source); console.log(result); /* Output: { api: { endpoint: "/v2" }, // ❌ timeout: 5000 is GONE! features: { darkmode: true } } */ The Pain: Because Object.assign() and spread operators perform a shallow merge, the top-level api object was completely overwritten. Your timeout key was wiped out silently, your dev build crashed, and your coffee is now freezing cold. 🪦
Act II: "I'll use an online merger!"
Desperate, you open Google and paste your internal API configurations and localized client settings into the first online-json-merger-free.com site you find.
Suddenly, a cold sweat hits you:
"Wait... did I just send our production database keys and API tokens to a server hosted in someone's basement?" 😳
The Paranoia: You spend the next hour rotating secret tokens and auditing git commits just to be safe.
Act III: Salvation (The 100% Local Deep Merge)
To save your Friday nights and preserve your sanity, here are two simple solutions that actually work:
Option A: The Vanilla JS Deep Merge
If you're writing code, stop using { ...a, ...b } for nested JSON. Use a recursive merge strategy instead:
function isObject(item) { return item && typeof item === "object" && !Array.isArray(item); } function deepMerge(target, source) { let output = Object.assign({}, target); if (isObject(target) && isObject(source)) { Object.keys(source).forEach((key) => { if (isObject(source[key])) { if (!(key in target)) { Object.assign(output, { [key]: source[key] }); } else { output[key] = deepMerge(target[key], source[key]); } } else { Object.assign(output, { [key]: source[key] }); } }); } return output; } // Now your nested keys survive! 🎉 const merged = deepMerge(target, source); console.log(merged.api.timeout); // 5000 Option B: Use JoinJSON (Zero Server Uploads)
If you just want a fast visual tool to merge JSON files in 2 seconds without writing boilerplate or risking privacy, I built JoinJSON.
- 🔒 100% Client-Side Privacy: All processing happens inside your browser's V8 engine. Zero bytes ever leave your machine.
- 🧠 Smart Deep Merging: Intelligently combines nested properties without wiping out non-conflicting keys.
- 🧹 Instant Validation: Highlights missing brackets, bad quotes, or trailing commas before they break your code.
🔗 Give your backspace key a break: https://www.joinjson.com/
💬 Over to you:
What is the most chaotic JSON syntax error or merge bug that has ever wasted your time? (Mine is definitely trailing commas inside arrays). Drop your horror stories below! 👇

