Why I built this
In April 2026 I was debugging a webhook payload from a Korean payment gateway (KG 이니시스) and needed to format the response to read it. I pasted it into the first JSON formatter that came up on Google. The payload contained a customer's name, phone number, masked card BIN, and order ID. The formatter site logged it. I know because three months later that same Google search surfaced a "popular recently formatted JSON examples" page on a competitor site — and someone's payment payload was on it. Not mine, but identical structure.
The popular online formatters are otherwise great products, but their business model is "we see your JSON for free." Anything you paste is on their server. Some explicitly keep paste history to show as examples. For anyone working with production data — authentication tokens, customer PII, internal API responses — that is unacceptable.
OhMyUnit's JSON formatter runs entirely in the browser. JSON.parse and JSON.stringify are native browser primitives — they execute in nanoseconds and never make a network call. Three rules: (1) nothing reaches our server, (2) clear line:column error messages instead of cryptic "unexpected token," (3) handles everything from one-line config to 10 MB API dumps without slowing down.
How it works under the hood
When you paste JSON, the textarea's value is read on every keystroke (debounced by ~150ms to avoid thrashing). We call JSON.parse(value) inside a try/catch block. If parsing succeeds, we call JSON.stringify(parsed, null, indent) with your chosen indent setting (2 spaces, 4 spaces, or tab) and render the result. If parsing fails, we extract the position from the SyntaxError message — modern browsers include "position N" in their JSON error messages — and convert that byte offset to a line:column coordinate for display.
JSON.parse is implemented in C++ inside the browser's JavaScript engine (V8 in Chrome/Edge, SpiderMonkey in Firefox, JavaScriptCore in Safari). It is roughly 5-10× faster than any JavaScript JSON parser library you could load. For a 5 MB JSON file, parsing takes ~30ms on a recent laptop. Stringification is similarly fast. The UI bottleneck is text rendering — a 50,000-line pretty-printed output takes longer to paint on screen than to compute.
Minify mode just calls JSON.stringify(parsed) with no indent argument, which produces the most compact serialization possible — exactly one space after colons and commas, nothing else. The output is guaranteed to be valid JSON that parses back to identical data structures.
Verify yourself: open DevTools → Network tab, clear the log, paste a JSON payload, and click Format. The list stays empty — no fetch or XHR request carries your data. This is structurally impossible for hosted formatters that run their parser on a server.
Real use cases
- Debugging API responses (Korean payment gateways, KakaoTalk webhooks): Webhook payloads from 토스페이먼츠, 카카오페이, NHN KCP arrive as minified JSON. Pretty-print them to trace fields, especially when the docs are incomplete.
- Validating config files before committing: tsconfig.json, package.json, .vscode/settings.json — paste yours here before commit to catch trailing commas or quote mismatches that would break the build.
- Cleaning up Postman / Insomnia exports: API collection exports come as one-line JSON. Format to read or diff between versions.
- Inspecting JWT payloads: Base64-decode the middle segment of a JWT, paste the result here to see claims, expiry, and roles in a readable form.
- Preparing fixtures for unit tests: Minify large JSON test fixtures to keep test files compact, or pretty-print mock data to make assertions obvious during code review.
vs other JSON formatters
How OhMyUnit's JSON formatter compares to the most-Googled alternatives as of May 2026:
| Feature | OhMyUnit | jsonformatter.org | JSONLint | json.parser.online.fr |
|---|---|---|---|---|
| Free tier | Yes | Yes (ads) | Yes | Yes |
| No upload to server | Yes | No | No | No |
| No paste history logging | Yes | Often | No history | Unknown |
| Schema validation | No | Yes | Yes | No |
| Line:column error pointer | Yes | Yes | Yes | Yes |
| Works offline | Yes (after load) | No | No | No |
| Max practical size | ~10 MB | ~5 MB | ~1 MB | ~1 MB |
| Source inspectable | Yes | No | No | No |
Where competitors win: JSONLint and jsonformatter.org have built-in JSON Schema validation, JSONPath query support, and tree-view visualizations. For schema-heavy work — testing API contracts, validating config against a published schema — they are more feature-rich. For "paste, fix indent, copy back" workflows (which is 80% of real use), our tool is faster, private, and works offline.
What this can't do
- JSON Schema validation. No "validate this JSON against this schema" feature. Use JSONLint or Ajv in your build pipeline.
- JSONPath queries. No $.users[?(@.age > 30)] style filtering. Use jq on the command line.
- JSON5 / JSONC. No support for comments or trailing commas. Strip them manually first.
- Diff two JSON files side-by-side. Use VS Code or jq diff for comparison work.
- Edit JSON as a tree. Text-only editing. For tree-view editing, JSON Editor Online is the established choice.
For schema validation, use Ajv in your build. For tree-view editing, JSON Editor Online. For command-line querying and diffing, jq remains unmatched.
Tips for best results
Use 2-space indent for git-tracked files. 4-space indent doubles the diff size for nested structures and many style guides (Google, Airbnb) prefer 2-space. Tab indent is contentious — use it only if your team standard requires it.
Minify before pasting into URL query strings. URL-encoded JSON in a query string gets enormous fast. Minify first, then URL-encode the result — saves roughly 40% of URL length.
For huge JSON (50+ MB), use jq instead. Browser textarea performance degrades sharply above 10 MB of pretty-printed text. Command-line jq handles gigabyte files comfortably.
Always validate API responses before parsing in production code. If the source could be malformed (untrusted user input, flaky third-party API), wrap JSON.parse in try/catch. Our error messages here are the same ones your production code will see.
FAQ
Why does my JSON show an error even though it looks fine? JSON is much stricter than the JavaScript object literals it resembles. Common offenders: trailing commas after the last element (valid in JS, invalid in JSON), single quotes instead of double quotes for strings, unquoted object keys (JSON requires quoted keys always), comments (JSON has no comment syntax), or hex/octal/leading-zero numbers. Our error message includes an approximate line:column pointer — the offending character is usually within a few characters of that location. If you copy-pasted from JavaScript code, paste it into a JS console first to evaluate it, then JSON.stringify the result.
Is my JSON sent anywhere? No. Parsing happens via the browser's native JSON.parse function, which is a synchronous in-memory operation. There is no fetch() or XMLHttpRequest in the entire pipeline. Open DevTools → Network tab, clear the log, paste your JSON, and click Format — the list stays empty. The only network activity is the initial page load. This matters because developers often paste sensitive payloads (API keys, auth tokens, customer PII captured from a debug session) into JSON formatters, and most hosted formatters log everything.
What is the difference between beautify and minify? Beautify (pretty-print) adds whitespace, newlines, and indentation to make JSON human-readable. Minify strips every byte of optional whitespace into a single line, producing the smallest possible payload — useful for HTTP request bodies where bytes matter, config files committed to git where diff noise should be minimized, or embedded JSON inside HTML attributes. Functionally identical for any JSON consumer; only the visual representation differs. Minify typically shrinks JSON by 30-60% versus 4-space indent.
Why would I use this instead of jsonformatter.org or JSONLint? Three reasons: privacy, speed, and offline use. JSONLint and jsonformatter.org have valid SaaS business models (ads, premium tiers) but they receive every JSON payload you paste — including any sensitive data inside. Our tool is fully client-side: nothing reaches our server. Speed: native JSON.parse runs at C speed, beating any network round-trip. Offline: after first page load, this tool works on a plane or in a tunnel. JSONLint does add nice schema validation features which we do not yet have, so for schema-heavy work it still beats us.
Does it support JSON5, JSONC, or comments? Currently no — we parse strict RFC 8259 JSON only. JSON5 (the lenient dialect allowing comments, trailing commas, unquoted keys) and JSONC (JSON with comments, used in VS Code config files) require separate parsers we have not added. If you have JSON5 input, strip the comments and trailing commas manually first. Most config-file JSONC (.vscode/settings.json) is small enough to clean by hand. JSON5 support is on the roadmap but unscheduled.
What is the maximum JSON size I can paste? Practically, anything that fits in your clipboard and your browser's memory. JSON.parse is fast — even 50 MB of JSON parses in under a second on a modern laptop. The UI textarea handles up to ~10 MB comfortably; beyond that, the browser's text rendering becomes the bottleneck (scrolling lags, syntax highlighting freezes). For multi-hundred-MB JSON, use jq or python -m json.tool on the command line. For everyday API responses, config files, and database exports, we handle anything you can paste.
My JSON has special characters — will they survive? Yes, if the source escapes them properly. JSON.parse handles all valid escape sequences (\\n, \\t, \\", \\\\, \\uNNNN for unicode), and JSON.stringify on the way out re-escapes them correctly. Korean characters (한글), emoji, accented Latin (café), Chinese, Japanese, and Arabic all pass through without issue. If you see ?? or □ in the output, the source bytes were already corrupted before paste — JSON itself preserves UTF-8 perfectly.
How can I sort keys alphabetically? Currently the formatter preserves the original key order. To alphabetize keys, you can paste this into the browser console: JSON.stringify(JSON.parse(your_json), Object.keys(JSON.parse(your_json)).sort(), 2). Alphabetical key ordering is useful for git diffs (key reordering between versions becomes a no-op) and config file consistency. We may add a "sort keys" toggle to the formatter in a future update; it is a single replacer-function change.
Why is my pretty-printed output shorter than expected? Almost certainly because your input had escaped newlines (\n as a literal string) that are not actually newlines in JSON. The string "line1\nline2" is a 13-character JSON string containing the literal characters l, i, n, e, 1, backslash, n, l, i, n, e, 2 — not a multi-line string. JSON has no multi-line string syntax. If you want actual newlines in JSON, the source must already have them encoded as \n inside the string value, which the JSON parser will faithfully preserve. The visual output looks compact because escaped newlines render as escape sequences, not breaks.
My output has scientific notation (1e+20) where I had a plain number — why? JavaScript numbers are double-precision floats, and JSON.stringify converts very large or very small numbers to scientific notation when the standard representation would be longer. 100000000000000000000 becomes 1e+20 because they are mathematically equal but the latter is shorter. If you need to preserve the literal representation (for example, a 32-character user ID stored as a number), encode it as a string in the source JSON. JavaScript loses precision above 2^53, so very large integers like Twitter snowflake IDs must always be strings.