I once spent an hour debugging a config loader before realizing the issue was a single trailing comma. A colleague had hand-edited a JSON config file and left a comma after the last property in an object:

{
  "host": "localhost",
  "port": 3000,
  "debug": true,  // ← This comma breaks strict JSON
}

JSON.parse() threw an error. The colleague insisted "JavaScript lets me do this in objects!" They were right about JavaScript — but dead wrong about JSON.

This is the single most confusing thing about JSON for developers coming from JavaScript. Let me break down what's valid where, and how to deal with the mismatch.

The Core Difference: JS Object Literal vs JSON

// This works in JavaScript:
const config = {
  name: "Alice",     // Unquoted key — valid JS
  age: 30,            // No trailing comma — valid JS
  role: "admin",     // ← Trailing comma — still valid JS!
};

// But this is what strict JSON requires:
const configJson = '{"name":"Alice","age":30,"role":"admin"}';
// No trailing commas. No unquoted keys. Double quotes only.

JavaScript's object literal syntax is lenient: unquoted keys, single quotes, trailing commas, comments — all allowed. The JSON object in JavaScript follows a different, strict specification (RFC 7159).

Trailing Commas: The Most Common Headache

A trailing comma is a comma after the last item in an array or the last property in an object.

// Array examples
const validArray = [1, 2, 3];
const trailingArray = [1, 2, 3,]; // Invalid JSON, valid JS

// Object examples  
const validObj = {"a": 1, "b": 2};
const trailingObj = {"a": 1, "b": 2,}; // Invalid JSON, valid JS

Why people write them: Git diffs. With trailing commas, adding a new property only changes one line instead of two:

{
  "a": 1,
-  "b": 2
+  "b": 2,
+  "c": 3
}

vs without trailing commas:

{
  "a": 1,
-  "b": 2
+  "b": 2,
+  "c": 3
}

See the difference? The first diff touches one line. The second touches two. Teams that hand-edit JSON a lot add trailing commas for cleaner diffs — and then JSON.parse() breaks.

Fixing Trailing Commas Programmatically

// Regex-based fix (simple but fragile)
function stripTrailingCommas(jsonString) {
  return jsonString
    .replace(/,\s*([}\]])/g, '$1')    // Remove trailing commas before ] or }
    .replace(/,\s*$/, '');            // Remove trailing comma at end of string
}

const broken = '{"items": [1, 2, 3,], "status": "ok",}';
const fixed = stripTrailingCommas(broken);
console.log(JSON.parse(fixed)); // ✅

Better approach: Use a relaxed parser like json5 that handles trailing commas natively:

npm install json5
const JSON5 = require('json5');

const withCommas = '{"items": [1, 2, 3,], "status": "ok",}';
const data = JSON5.parse(withCommas); // Works without stripping

Or just use the JSON Formatter tool's Validate feature — it reports the exact line and position of trailing commas, so you can find and remove them manually.

Single Quotes: The Second Most Common Issue

JSON requires double quotes for all strings, including property keys. Single quotes are valid JavaScript but invalid JSON.

// These all fail JSON.parse:
JSON.parse("{'name': 'Alice'}");       // Single-quoted keys
JSON.parse('{"name": \'Alice\'}');     // Single-quoted values
JSON.parse("{'items': [1, 2, 3]}");    // Mixed

// This works:
JSON.parse('{"name": "Alice"}');       // Double quotes only

Where single quotes sneak in:

  1. Copying from console.log output: console.log({name: "Alice"}) displays as {name: "Alice"} but if you copy it, some browser dev tools wrap string values differently.
  2. Python dict repr: Python's str() on a dict uses single quotes by default: {'name': 'Alice'}. If you paste that into a JavaScript parser, it fails.
  3. Hand-typed configs: People writing JSON by hand often use single quotes out of habit from JavaScript/TypeScript object literals.

Fixing Single Quotes

function fixSingleQuotes(jsonString) {
  // Replace single-quoted keys with double-quoted keys
  let s = jsonString.replace(/'([^']+)'\s*:/g, '"$1":');
  // Replace single-quoted string values with double-quoted values
  s = s.replace(/:\s*'([^']*)'/g, ': "$1"');
  return s;
}

const input = "{'name': 'Alice', 'items': [1, 2, 3]}";
console.log(JSON.parse(fixSingleQuotes(input))); // ✅

Important: This simple regex approach fails if your string values contain colons or quotes. For production code, use json5 or a proper tokenizer.

Unquoted Keys (Another JavaScript-ism)

// Valid JavaScript — invalid JSON
{ name: "Alice", age: 30 }

This happens when someone copies a JavaScript object literal. The fix is similar to single quotes — wrap the keys in double quotes.

function fixUnquotedKeys(str) {
  // Match word-boundary keys followed by colon
  return str.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":');
}

The Real-World Fix: JSON5 or Manual Conversion

If you're dealing with a lot of non-standard JSON, don't write a fragile parser. Use json5:

const JSON5 = require('json5');

// All of these work with JSON5:
JSON5.parse("{name: 'Alice',}");            // Unquoted key, single quotes, trailing comma
JSON5.parse("{'name': \"Alice\",}");        // Mixed quotes
JSON5.parse("{name: 'Alice', /* comment */}"); // Comments too

When you can't install a package, paste the problematic JSON into the JSON Formatter. Its validation engine tells you exactly what's wrong — "Trailing comma at line 3, column 15" — so you can fix it manually.

Converting Non-Standard to Strict JSON

Here's a utility I use for converting JavaScript object literals to strict JSON:

function toStrictJSON(input) {
  // Step 1: Remove comments (single-line only)
  let s = input.replace(/\/\/.*$/gm, '');
  // Step 2: Fix unquoted keys
  s = s.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":');
  // Step 3: Fix single quotes → double quotes (simple cases)
  s = s.replace(/'/g, '"');
  // Step 4: Remove trailing commas
  s = s.replace(/,\s*([}\]])/g, '$1');
  // Step 5: Remove trailing comma at string end
  s = s.replace(/,\s*$/, '');
  
  try {
    return JSON.parse(s);
  } catch (e) {
    throw new Error(`Could not convert: ${e.message}`);
  }
}

It's not perfect — string values containing colons or quotes need proper tokenization — but it handles 95% of the cases I see in practice.

FAQ

Q: Why does JavaScript allow trailing commas in object literals but JSON.parse doesn't?

A: The JSON specification (RFC 7159) explicitly forbids trailing commas. JavaScript object literals are a separate language feature with different rules. JSON is a data interchange format, not JavaScript.

Q: Can I configure JSON.parse to accept trailing commas?

A: No. The native JSON.parse follows the strict specification. You need a third-party parser like json5 or a pre-processing step.

Q: Are there valid use cases for single quotes in JSON?

A: No. The JSON spec requires double quotes for strings and property names. Single quotes are always invalid.

Q: How do I fix a 50MB JSON file with single quotes?

A: Use a streaming parser like json5 with streams, or write a character-by-character converter. Don't load the whole file into memory with JSON.parse.

Q: What about backtick strings?

A: Template literals (backtick strings) are not valid JSON at all. The only valid string delimiters in JSON are double quotes.

Q: Can the JSON Formatter tool handle files with trailing commas?

A: The validator will flag them as syntax errors. Use the Format or Validate feature to see exactly where. For actual fixing, strip them manually or use a relaxed parser first.

Q: How do teams handle this in CI/CD?

A: Add a JSON validation step in your pipeline using jsonlint or the JSON Formatter API. Reject any PR with trailing commas or single quotes before they reach production.