← Download MyJS

MyJS block

parseJSONC 1.0.0

Parses a JSON string that may contain comments and trailing commas.

Download with this
Exports
parseJSONC
Works in
Browser and Node.js
The code of version 1.0.0
/**
 * Parses a JSON string that may contain comments and trailing commas (JSONC).
 * Line (`//`) and block comments are removed, along with trailing commas
 * before `]` or `}`. Whitespace that JSON does not allow, such as a BOM or a
 * no-break space, is treated as a space when it appears outside strings.
 * Removed text is replaced with spaces and line breaks are kept, so the line
 * and column numbers in parse errors still match the original text.
 * @param {string} text
 *    A valid JSON (with comments) string.
 * @param {function(string, *): *} [reviver]
 *    A function that transforms the results. This function is called for each
 *    member of the object. If a member contains nested objects, the nested
 *    objects are transformed before the parent object is.
 * @returns {JSONValue}
 *    The JavaScript value that `text` represents, or whatever `reviver`
 *    returns for the root value if a reviver is given.
 * @throws {SyntaxError}
 *    If `text` is not a valid JSON (with comments) string.
 *
 * @example <caption>Comments and trailing commas</caption>
 * parseJSONC(`{
 *   // Server settings
 *   "host": "localhost",
 *   "port": 8080,
 *   "tags": ["web", "api",],
 * }`);
 * // → { host: 'localhost', port: 8080, tags: ['web', 'api'] }
 *
 * @example <caption>Comment markers inside strings are left alone</caption>
 * parseJSONC('{"url": "https://example.com", "note": "say \\"hi\\" // here"}');
 * // → { url: 'https://example.com', note: 'say "hi" // here' }
 *
 * @example <caption>Using a reviver</caption>
 * parseJSONC(
 *   '{"created": "2026-01-01", // ISO date\n}',
 *   (key, value) => key === 'created' ? new Date(value) : value
 * );
 * // → { created: Date(2026-01-01T00:00:00.000Z) }
 *
 * @example <caption>Invalid input throws</caption>
 * parseJSONC('{"a": 1 // missing closing brace');
 * // throws SyntaxError
 */
function parseJSONC(text, reviver) {
  // Blank out comments and non-JSON whitespace, preserving line/column offsets.
  text = text.replace(
    /("(?:[^"\\\r\n]|\\.)*")|\/\/[^\r\n]*|\/\*[\s\S]*?\*\/|[^\S\r\n\t ]+/g,
    (m, q) => q ?? m.replace(/[^\r\n\t]/g, ' ')
  );
  // Remove trailing commas.
  text = text.replace(
    /("(?:[^"\\\r\n]|\\.)*")|,(?=\s*[\]}])/g,
    (m, q) => q ?? ' '
  );
  // Parse and return the normalized JSON.
  return JSON.parse(text, reviver);
}

/** @typedef {string | number | boolean | null | JSONObject | JSONArray} JSONValue */
/** @typedef {Record<string,JSONValue>} JSONObject */
/** @typedef {JSONValue[]} JSONArray */

Versions

  1. 1.0.0 Oct 22, 2026

    Initial

JSDoc