import { JsonNested } from "./zod"; import { parse, isSafeNumber, isNumber } from "lossless-json"; /** * Deeply parses a JSON string or object for nested stringified JSON * @param json JSON string or object to parse * @returns Parsed JSON object */ export function deepParseJson(json: unknown): unknown { if (typeof json === "string") { try { const parsed = JSON.parse(json); if (typeof parsed === "number") return json; // numbers that were strings in the input should remain as strings return deepParseJson(parsed); // Recursively parse parsed value } catch (e) { return json; // If it's not a valid JSON string, just return the original string } } else if (typeof json === "object" && json !== null) { // Handle arrays if (Array.isArray(json)) { for (let i = 0; i < json.length; i++) { json[i] = deepParseJson(json[i]); } } else { // Handle nested objects for (const key in json) { // Ensure we only iterate over the object's own properties if (Object.prototype.hasOwnProperty.call(json, key)) { (json as Record)[key] = deepParseJson( (json as Record)[key], ); } } } return json; } return json; } export const parseJsonPrioritised = ( json: string, ): JsonNested | string | undefined => { try { return parse(json, null, (value) => { if (isNumber(value)) { if (isSafeNumber(value)) { // Safe numbers (integers and decimals) can be converted to Number return Number(value.valueOf()); } else { // For large integers beyond safe limits, preserve string representation return value.toString(); } } return value; }) as JsonNested; } catch (error) { return json; } };