/** * 尝试解析宽松的 JSON-like 字符串(支持单引号、未加引号的键、尾随逗号等常见格式)。 * 优先使用原生 JSON.parse,失败后做基本清洗并重试。 */ function parseLooseJSON(input: string) { let s = (input || '').trim() if (!s) return null // 1) 直接尝试 JSON.parse try { return JSON.parse(s) } catch (e: any) { // continue } // 移除注释 function removeComments(str: string) { return str.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/.*$/gm, '') } // 基本清理 function cleanString(str: string) { let t = str t = t.replace(/,(\s*[}\]])/g, '$1') t = t.replace(/([\{\s,])([A-Za-z0-9_$@\-]+)\s*:/g, '$1"$2":') t = t.replace(/'([^'\\]*(\\.[^'\\]*)*)'/g, (_, inner) => '"' + inner.replace(/"/g, '\\"') + '"') return t } // 2) 提取第一个平衡的对象/数组文本(忽略字符串内的括号) const firstBraceIdx = Math.min( ...['{', '['] .map((c) => { const idx = s.indexOf(c) return idx === -1 ? Infinity : idx }) .filter((v) => v !== undefined) ) if (firstBraceIdx !== Infinity) { let depth = 0 let inStr = false let strChar = '' let esc = false for (let i = firstBraceIdx; i < s.length; i++) { const ch = s[i] if (esc) { esc = false continue } if (ch === '\\') { esc = true continue } if (inStr) { if (ch === strChar) inStr = false continue } else { if (ch === '"' || ch === "'") { inStr = true strChar = ch continue } if (ch === '{' || ch === '[') depth++ else if (ch === '}' || ch === ']') { depth-- if (depth === 0) { s = s.substring(firstBraceIdx, i + 1) break } } } } } // 3) 清理并解析 s = removeComments(s) s = cleanString(s) try { return JSON.parse(s) } catch (e: any) { // 错误时返回空对象 return {} } } export { parseLooseJSON }