How JSON Forge Turns “position 4127” Into a Real Error, In Your Browser

Written by

in

Last month I pasted a 4MB webhook payload into a random online JSON formatter to find why one field was null. The JSON had a customer’s full name, email, a Stripe customer id, and an internal auth token in the headers block. I hit format, got my answer, closed the tab. Then it hit me: I had no idea where that request just went.

That’s the whole reason I keep coming back to JSON Forge — it runs entirely in the browser, so the payload never leaves the tab. But the privacy angle is only half of it. The part I actually want to talk about is how a browser-only formatter pulls off things people assume need a server: 10MB files without freezing, exact error line/column, and a clickable tree that shows the JSONPath of any node.

The error message trick every JSON tool should steal

Native JSON.parse() gives you a miserable error. In V8 you get something like Unexpected token } in JSON at position 4127. Position 4127 of what? Nobody counts characters. You want a line and column.

The fix is three lines. JSON.parse hands you the absolute character offset in the message, and you turn that into line/col by slicing the input and counting newlines:

const match = e.message.match(/position (\d+)/);
if (match) {
  const pos = parseInt(match[1]);
  const before = input.substring(0, pos);
  const line = before.split('\n').length;
  const col  = pos - before.lastIndexOf('\n');
  msg += ` (line ${line}, col ${col})`;
}

That’s it. lastIndexOf('\n') finds the start of the current line, subtract from the position, and you have the column. No parser library, no AST. This is exactly what JSON Forge does to turn position 4127 into line 118, col 23. One caveat: the message format isn’t standardized. Firefox says line 118 column 23 directly, Safari phrases it differently. If you ship this, regex the position defensively and fall back to the raw message.

Why “large file support” is mostly about not painting

The naive formatter does el.innerHTML = syntaxHighlight(json) and dies on anything past a couple hundred KB — you’re asking the browser to build a DOM node per token. For a 10MB file that’s millions of spans.

The trick isn’t a Web Worker. Parsing 10MB with JSON.parse takes tens of milliseconds; that’s not your bottleneck. Rendering is. JSON Forge guards the expensive path with a hard cutoff:

function renderHighlighted(json) {
  // Skip per-token highlighting past 500KB
  if (json.length > 500000) {
    outputEl.textContent = json;   // plain text, one node
    return;
  }
  // ...build highlighted spans for smaller inputs
}

Above the threshold you drop to a single text node. You lose color, you keep your framerate. It’s an honest tradeoff and it’s the right one — nobody is visually scanning 10MB of colorized JSON anyway. For structured browsing at that size, the collapsible tree view is what you actually want, because it only builds DOM for nodes you’ve expanded.

Clicking a node to get its JSONPath

The tree view builds each node recursively and stamps the path onto the element as it goes. When you click, it reads that path back out — no reverse lookup, no walking parent pointers:

function buildTreeNode(value, path, depth) {
  // path is passed down: '$', '$.user', '$.user.emails[0]' ...
  el.dataset.path = path;
  el.addEventListener('click', (e) => {
    e.stopPropagation();
    showPath(path);   // renders $ › user › emails › [0]
  });
}

Because the path is computed on the way down the recursion, every node already knows its own address. Clicking a deeply nested value gives you $.data.items[3].metadata.tags[0] instantly, which you can paste straight into a jq filter or a JSONPath query in your code. That round trip — visual tree to copyable path — is the thing I use daily.

The auto-fix is regex, and that’s fine (if you know the edges)

The “repair broken JSON” button isn’t a grammar-aware parser. It’s a short stack of regex replacements applied in order:

fixed = fixed.replace(/,(\s*[}\]])/g, '$1');        // trailing commas
fixed = fixed.replace(/'/g, '"');                    // single → double quotes
fixed = fixed.replace(/(\{|,)\s*([a-zA-Z_$][\w$]*)\s*:/g, '$1"$2":'); // unquoted keys

This nails the three things you actually hit copy-pasting from JavaScript source or a Python dict: trailing commas, single quotes, and bare keys. It deliberately does not try to quote unquoted string values — that’s ambiguous with numbers and booleans, so it bails rather than corrupt your data. The single-quote replace is the sharp edge: if a string value legitimately contains an apostrophe ("can't" written as 'can\'t'), a blunt global replace breaks it. So the tool re-runs JSON.parse after fixing and tells you if the repair didn’t actually produce valid JSON, instead of silently handing back garbage. Know the limits and it saves you 30 seconds every time.

Why browser-only is the real feature

Here’s the uncomfortable part. Most “free online JSON formatter” sites POST your input to a backend, and a good number log it. I’ve written before about how your online SQL formatter might be logging your database password — the same logic applies double to JSON, because JSON is where the tokens, PII, and API responses live.

You can verify JSON Forge yourself: open DevTools, go to the Network tab, paste a giant payload, format it. Zero requests. Everything — parse, highlight, tree, JSONPath, auto-fix — happens in JSON.parse and DOM APIs that shipped in your browser years ago. Turn off your Wi-Fi and it still works, because it’s a PWA you can install and run offline. That’s not a marketing checkbox; it’s the difference between a tool you can paste production data into and one you can’t.

If you want the same guarantee for other formats, the rest of our browser-only set follows the same rule: Base64Lab for encode/decode/preview, DiffLab for side-by-side text compare, and HashForge for hashing. None of them phone home.

Worth having on the shelf

If you spend your days elbow-deep in JSON payloads and event streams, the book that made me think clearly about the shape of that data is Martin Kleppmann’s Designing Data-Intensive Applications (affiliate link — full disclosure). It’s not about formatting; it’s about why your data looks the way it does across queues, logs, and APIs, and it’s the one systems book I re-read.

Try JSON Forge the next time you’re about to paste a payload into some random site. Then check the Network tab and see the difference for yourself.


Join https://t.me/alphasignal822 for free market intelligence.

📧 Get weekly insights on security, trading, and tech. No spam, unsubscribe anytime.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Also by us: StartCaaS — AI Company OS · Hype2You — AI Tech Trends