How to fix malformed json returned by api responses
- Step 1Capture the raw response body — In browser DevTools, open the Network tab, find the failing request, and copy the Response body — the raw text, not the formatted/parsed preview. Or
curl <url>and copy stdout. The raw bytes are where the invalid characters live. - Step 2Paste it into the fixer — Paste the body into the input, or save it to a
.json/.txtfile and drop it on the dropzone. Reading happens locally viafile.text(); nothing about the response leaves your machine. - Step 3Pick an indent and click Fix JSON — Choose 2 or 4 spaces, then Fix JSON. The tool first tries
JSON.parseon the body as-is; if it throws, the five repair passes run and parsing is retried. - Step 4Read the Fixes applied list — Each label tells you exactly what the API got wrong:
Removed trailing commasmeans a serializer bug;Added quotes to unquoted object keysmeans the backend emitted a JS literal;Replaced undefined with nullmeans a JSundefinedleaked into the body. This list is your bug-report evidence. - Step 5Decide source vs client fix from the banner — Green means the body is now usable for inspection. Yellow means a non-repairable corruption remains — NaN, JSONP wrapper, leading zeros, or truncation. Note which, because those require a server fix or a documented client pre-processor, not this tool.
- Step 6Copy the evidence or build a typed model — Copy the fixed body into your bug report, or once it's valid, generate a TypeScript type or Zod schema from it to harden your client against the next malformed response.
API body errors: fixable vs not
Which malformed-response patterns this tool repairs, and which need a server fix or a client pre-processor. The right column links the correct next step.
| Pattern in the body | Auto-fixed? | If not, what to do |
|---|---|---|
| Trailing comma after last element | Yes — trailing-comma pass | n/a |
'single' quoted keys/values | Yes — quote pass | n/a |
Bare unquoted: keys | Yes — key-quote pass | n/a |
Literal undefined value | Yes — undefined→null pass | n/a |
| Comma dropped between two objects on separate lines | Yes — missing-comma pass | n/a |
NaN / Infinity numeric values | No | Server: emit null or a number. Client: .replace(/\bNaN\b/g,'null') before parse |
callback({...}) JSONP wrapper | No | Strip the wrapper: body.replace(/^[\w$.]+\(/, '').replace(/\);?\s*$/, '') |
Leading-zero 01234 or hex 0xFF | No | Server fix; or coerce in a client pre-processor |
| Truncated body (connection cut) | No | Retry the request; partial JSON can't be reconstructed |
Indent + limits for response bodies
The options and ceilings that apply when fixing API responses on this tool.
| Setting | Value | Note |
|---|---|---|
| Output indent | 2 or 4 spaces | Only two choices; output is always re-serialized |
| Free file size | 2 MB | TIER_LIMITS.free.json.fileBytes — covers almost any single response body |
| Pro file size | 100 MB | For large paginated dumps concatenated into one file |
| Row limit | None on this tool | freeRowLimit is null for the fixer |
| Accepted types | .json .ndjson .jsonl .txt | Paste also works for body text copied from DevTools |
Cookbook
Real malformed API bodies, the fixes applied, and the banner you'd see. Endpoints and values are anonymised.
Hand-rolled serializer leaves a trailing comma
ExampleAn internal Go/Python service builds JSON by string concatenation and leaves a comma after the last array item. The client's parse fails; the fixer strips it.
Raw response body:
{
"items": [
{"id": 1},
{"id": 2},
]
}
Fixes applied (1):
✓ Removed trailing commas
Banner: Fixed & valid JSON — now safe to inspect and use as a test fixture.Backend returns a JS object literal, not JSON
ExampleA template emitted unquoted keys and single-quoted strings. Two passes fire; the body becomes valid and you have proof of the server bug.
Raw response body:
{ status: 'ok', code: 200, data: 'pending' }
Fixes applied (2):
✓ Replaced single quotes with double quotes
✓ Added quotes to unquoted object keys
Banner: Fixed & valid JSON
Bug report line: 'Endpoint returns a JavaScript object literal
(unquoted keys, single quotes) instead of RFC 8259 JSON.'undefined leaked from the backend's JSON.stringify
ExampleA Node service spread an object with an undefined property in a way that serialized the literal. The fixer maps the value to null; the pass is string-aware, so any string field containing the word undefined is left untouched.
Raw response body:
{ "user": "sam", "avatar": undefined }
Fixes applied (1):
✓ Replaced undefined with null
Banner: Fixed & valid JSON
Server fix: omit the key entirely, or set it to null on the server.NaN in a numeric field — not fixable here
ExampleA metrics endpoint divided by zero and serialized NaN. No pass targets it; the fixer is honest and reports the body still invalid.
Raw response body:
{ "avgLatencyMs": NaN, "count": 0 }
Fixes applied (0)
Banner: Partially fixed — output may still have issues
Client workaround before parse:
const safe = body.replace(/\bNaN\b/g, 'null');
const data = JSON.parse(safe);JSONP callback wrapper — strip before fixing
ExampleA legacy JSONP endpoint wraps JSON in a function call. The fixer can't unwrap it, so the wrapper survives. Strip it yourself, then the inner JSON often needs no fix at all.
Raw response body:
jsonpCallback({"id":1,"name":"a"});
Fixes applied (0)
Banner: Partially fixed
Unwrap first:
const inner = body.replace(/^[\w$.]+\(/, '').replace(/\);?\s*$/, '');
// inner = {"id":1,"name":"a"} — already validErrors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
undefined inside a string field is preserved
By designThe undefined → null pass is string-aware: it tracks string state while walking the body, so a string containing the word undefined (e.g. an error message "state is undefined") is left exactly as-is. Only a bare undefined value is rewritten to null. You can trust a fixed API body as a test fixture without reviewing its string fields for the word undefined.
NaN / Infinity from a numeric serializer
InvalidCommon in metrics and analytics endpoints that divide by zero or overflow. No pass touches them; the body stays invalid. Fix the server to emit null/finite numbers, or pre-process the client response with a targeted .replace(/\bNaN\b/g,'null') and document it.
JSONP callback wrapper
Invalidcallback({...}) is not JSON and the fixer won't unwrap it. Strip the wrapper with body.replace(/^[\w$.]+\(/, '').replace(/\);?\s*$/, '') first; the inner payload is frequently already valid. JSONP is legacy — migrate to CORS where you can.
Leading-zero or hex numbers
Invalid{ "acct": 01234 } or { "flags": 0xFF } are valid in some languages but not JSON, and no pass normalizes numbers. They survive and the body is reported invalid. These usually mean the server should quote the value as a string (account numbers especially).
Truncated response body
FailA dropped connection or a Content-Length mismatch leaves the body cut off mid-object. The fixer can't reconstruct missing data or add the closing brackets — it returns the fragment and reports it invalid. Retry the request; partial JSON is unrecoverable.
Apostrophe inside a single-quoted value
RejectIf the backend emitted 'it's fine', the value-quote pass ('[^']*') stops at the inner apostrophe and produces broken output. Fix the server to use double quotes, or correct the value by hand.
Body is already valid JSON
ExpectedIf the response actually parses, no passes run and you get re-indented output with No fixes needed. Useful when the real failure was elsewhere in your client (wrong content-type handling, double-decoding) rather than in the body.
Pasting the parsed object instead of the raw body
By designIf you paste DevTools' formatted/parsed preview rather than the raw response, it's often already valid (DevTools normalized it) and the fixer reports no fixes — hiding the real corruption. Always copy the raw Response tab text, not the parsed preview.
Response larger than 2 MB on free tier
BlockedFree JSON files cap at 2 MB. A large paginated dump concatenated into one file may exceed that and prompt an upgrade; Pro raises the ceiling to 100 MB.
Frequently asked questions
An API returns invalid JSON — can this make it usable?
If the corruption is one of the five fixable patterns (trailing commas, single quotes, unquoted keys, undefined, dropped commas between objects), yes — the body becomes parseable and you can inspect it or use it as a test fixture. If it's NaN, JSONP, leading zeros, or truncation, the tool reports it still-invalid; those need a server fix or a documented client pre-processor.
Should I paste the raw body or the parsed object?
Always the raw body from DevTools' Response tab (or curl stdout). The parsed/preview view in DevTools has already normalized the data, so pasting it hides the real corruption — the fixer would report no fixes and you'd never see the underlying problem.
Does it fix NaN and Infinity in API responses?
No. They're a frequent metrics-endpoint bug but no pass targets them, so the body comes back unchanged and invalid. Fix the server to emit null or finite numbers, or add a client pre-processor body.replace(/\bNaN\b/g,'null') before JSON.parse and document the workaround.
Can it unwrap a JSONP callback response?
No — it doesn't strip the callback(...) wrapper. Remove it yourself with body.replace(/^[\w$.]+\(/, '').replace(/\);?\s*$/, ''); the inner JSON is usually already valid. JSONP is legacy and CORS is the modern replacement.
The fixer turned a value in my response to null — why?
The undefined → null pass rewrites a bare undefined VALUE to null. It is string-aware — it tracks string state as it walks the body — so the word undefined inside a string value (e.g. an error message) is preserved, not changed. If a value turned to null, it was an actual undefined value, not a string.
Can I use this to build a regression test fixture?
Yes — a common workflow. Capture the broken body, fix it to valid JSON, and save it as a fixture so your client's parsing logic can be tested against the real shape. Then generate a TypeScript type or Zod schema from the fixed body to validate future responses at runtime.
Does it process paginated NDJSON streams?
Not line-by-line. It treats the whole input as one document. A streamed NDJSON response (one object per line) won't be repaired correctly here — see the log-parsing guide for the per-line approach to newline-delimited JSON.
Is the response data sent anywhere?
No. The body is read and fixed entirely in your browser; nothing reaches JAD Apps servers. This matters when the response contains tokens, PII, or internal data. A signed-in run records only an anonymous counter (no content).
How do I know the fix didn't change the meaning of the data?
The green banner means it's syntactically valid, not semantically identical. The only data-affecting pass is undefined→null, and it is string-aware: it changes only a bare undefined value, never the word undefined inside a string. To be certain the structure matches, diff the fixed body against your expected shape with the JSON diff tool.
Can I control the indentation of the fixed body?
Yes — 2 or 4 spaces, the only two options. The fixer always re-serializes via JSON.stringify, so the output is consistently formatted. For compact single-line output use the minifier afterward.
What if the response uses a non-JSON content type but is meant to be JSON?
Content-type doesn't matter to this tool — it operates on the text you paste. If a text/plain endpoint returns JSON-shaped text with syntax errors, paste it here and fix it the same way. Fix the server's Content-Type header separately.
What's the size limit for a response body?
2 MB on the free tier, which comfortably covers virtually any single API response. Concatenated paginated dumps that exceed 2 MB need Pro (100 MB). There's no row limit on this tool.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.