parseJSON
The parseJSON utility provides a safe and robust way to parse JSON strings. It includes built-in error handling, support for default values, optional validation, and a customizable reviver function, ensuring that your application doesn't crash on malformed input.
Implementation
View Source Code
ts
import { Logit } from '@vielzeug/logit';
import { isNil } from '../typed/isNil';
import { isString } from '../typed/isString';
type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
// #region ParseJSONOptions
type ParseJSONOptions<T> = {
defaultValue?: T;
// biome-ignore lint/suspicious/noExplicitAny: -
reviver?: (key: string, value: any) => any;
// biome-ignore lint/suspicious/noExplicitAny: -
validator?: (value: any) => boolean;
silent?: boolean;
};
// #endregion ParseJSONOptions
/**
* Parses a JSON string and returns the resulting object.
*
* @example
* ```ts
* const json = '{"a":1,"b":2,"c":3}';
* const result = parseJSON<Record<string, number>>(json, {
* defaultValue: { a: 0, b: 0, c: 0 },
* validator: (value) => Object.values(value).every(v => typeof v === 'number'),
* errorHandler: (err) => console.warn('Parsing failed:', err.message),
* silent: true
* });
* console.log(result); // { a: 1, b: 2, c: 3 }
* ```
*
* @template T - The expected type of the parsed JSON.
* @param json - The JSON string to parse. If not a string, it is returned as is.
* @param options - Configuration options for parsing.
*
* @returns The parsed object if successful, otherwise the default value.
*/
export function parseJSON<T extends JSONValue>(json: unknown, options: ParseJSONOptions<T> = {}): T | undefined {
const { defaultValue, reviver, validator, silent = false } = options;
if (!isString(json)) return isNil(json) ? defaultValue : (json as T);
try {
const parsed = JSON.parse(json as string, reviver);
if (validator && !validator(parsed)) {
throw new TypeError('Parsed JSON does not match the expected structure');
}
return parsed ?? defaultValue;
} catch (err) {
if (!silent) {
Logit.error('parseJSON() -> failed to parse object', err);
}
return defaultValue;
}
}Features
- Isomorphic: Works in both Browser and Node.js.
- Safe Parsing: Automatically catches and handles syntax errors silently or with logging.
- Fallback Support: Specify a default value to return if parsing fails.
- Integrated Validation: Pass a validator function to ensure the parsed data meets your requirements.
- Reviver Support: Full compatibility with the native
JSON.parsereviver parameter.
API
Type Definitions
ts
type ParseJSONOptions<T> = {
defaultValue?: T;
// biome-ignore lint/suspicious/noExplicitAny: -
reviver?: (key: string, value: any) => any;
// biome-ignore lint/suspicious/noExplicitAny: -
validator?: (value: any) => boolean;
silent?: boolean;
};ts
function parseJSON<T>(json: unknown, options?: ParseJSONOptions<T>): T | undefined;Parameters
json: The data to parse. If it's not a string, it will be returned as-is (if it's already an object/array) or substituted with thedefaultValue.options: Optional configuration:defaultValue: The value to return if parsing fails or validation fails.reviver: A function that transforms the results as they are parsed.validator: A function that receives the parsed value and must returntruefor the result to be considered valid.silent: Iftrue, suppresses error logging to the console when parsing fails (defaults tofalse).
Returns
- The parsed value, or the
defaultValueif parsing or validation fails.
Examples
Basic Safe Parsing
ts
import { parseJSON } from '@vielzeug/toolkit';
// Valid JSON
parseJSON('{"active": true}'); // { active: true }
// Invalid JSON with fallback
parseJSON('invalid { json', { defaultValue: { active: false } });
// { active: false }Parsing with Validation
ts
import { parseJSON } from '@vielzeug/toolkit';
const raw = '{"id": 123, "name": "Alice"}';
// Validate that 'id' is a number
const user = parseJSON(raw, {
validator: (v) => typeof v.id === 'number',
defaultValue: { id: 0, name: 'Guest' },
});Using a Reviver
ts
import { parseJSON } from '@vielzeug/toolkit';
const raw = '{"amount": 42}';
// Double all numbers during parsing
const doubled = parseJSON(raw, {
reviver: (k, v) => (typeof v === 'number' ? v * 2 : v),
});
// { amount: 84 }Implementation Notes
- If the input
jsonis already an object or array (notnull), it skips theJSON.parsestep but still runs thevalidatorif provided. - If
nullorundefinedis passed as the input, it immediately returns thedefaultValue. - Throws nothing by default; all errors are caught and handled based on the
silentoption.