Javascript is required

Invalid JSON: BOM, Zero-Width & Commas

Find JSON parsing errors caused by UTF-8 BOM markers, zero-width characters, trailing commas, and other invisible input artifacts in API payloads.

Author: Tiny's Tool Core Team•Updated: 2026-09-14

INTERACTIVE TOOL DIAGNOSTIC WORKBENCH

Test this issue live in your browser

JSON Validator & Error Locator→

Start with the original input

Run JSON.parse on the exact API response before attempting any repair. Check the HTTP status and Content-Type: an HTML error page is not JSON. Error messages and positions vary by JavaScript engine.

BOM and invisible characters

Some editors offer UTF-8 with BOM. If a decoded string begins with U+FEFF, JSON.parse rejects it; remove only that initial marker when your input contract permits it. Do not assume every editor adds a BOM.

A zero-width character outside a JSON string is not JSON whitespace. Inside a quoted key or value it can be valid data. In particular, U+200D joins Emoji sequences. Report these characters for review; never delete them globally.

Trailing commas and quoted text

A comma before a closing bracket can be a syntax error, but the text inside a quoted string must remain unchanged. Single quotes, comments and unescaped control characters require separate diagnosis, not a global replacement.

Conservative repair with a string-aware scanner

This standalone TypeScript function tracks quoted strings and escaped quotes. It removes only a leading BOM and trailing commas outside strings, and offers a candidate only if JSON.parse accepts the complete result. Review changes before using the output.

ts

/** Conservative repair: preserve string contents; never strip invisible characters globally. */
export function repairJsonSyntax(input: string): { candidate?: string; trailingCommaFound: boolean } {
    const text = input.charCodeAt(0) === 0xfeff ? input.slice(1) : input;
    let output = "";
    let inString = false;
    let escaped = false;
    let previous = "";
    let trailingCommaFound = false;
    for (let index = 0; index < text.length; index++) {
        const char = text[index];
        if (inString) {
            output += char;
            if (escaped) escaped = false;
            else if (char === "\\") escaped = true;
            else if (char === '"') { inString = false; previous = '"'; }
            continue;
        }
        if (char === '"') inString = true;
        if (char === ",") {
            let next = index + 1;
            while (next < text.length && /[\x20\t\r\n]/.test(text[next])) next++;
            const closes = text[next] === "]" || text[next] === "}";
            if (closes && previous && !"[{,:".includes(previous)) {
                trailingCommaFound = true;
                continue;
            }
        }
        output += char;
        if (!/[\x20\t\r\n]/.test(char)) previous = char;
    }
    // Only offer a repair if the complete candidate is valid JSON.
    try {
        JSON.parse(output);
        return { candidate: output === input ? undefined : output, trailingCommaFound };
    } catch {
        return { trailingCommaFound };
    }
}

Verify that valid data stays unchanged

Test quoted commas, escaped quotes, backslashes, nested arrays and Emoji. Valid JSON must remain byte-for-byte unchanged. Inputs such as [,] or {,} must not become empty containers. A token split by an invisible character must still fail.

ts

const original = JSON.stringify({ text: ",}", emoji: "👩‍💻" });

console.assert(repairJsonSyntax(original).candidate === undefined);

console.assert(repairJsonSyntax("[,]").candidate === undefined);

console.assert(repairJsonSyntax('{"items":[1,2,],}').candidate === '{"items":[1,2]}');

Locate and review remaining errors

Use /tools/json/json-validator to inspect the original error and any available line/column. An unavailable position is not necessarily the first character. Confirm key names and values against the API contract after repair.

For HTML responses, double parsing and truncated payloads, see /articles/json-unexpected-token. For encoding and surrogate pairs, see /articles/unicode-json-escapes.

Data handling and limitations

The tool parses locally and does not intentionally upload pasted input. Minimize production samples and remove secrets before sharing. A successful JSON.parse proves syntax validity, not schema correctness, unique keys or exact handling of large integers.

References

RFC 8259: JSON grammar, strings and UTF-8