| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 |
- /**
- * Safely parses JSON from a string, handling markdown code blocks and leading/trailing text.
- */
- export function safeParseJson<T = any>(text: string): T | null {
- if (!text) return null;
- let jsonStr = text.trim();
- // 1. Try to extract JSON from markdown code blocks if they exist
- // Matches ```json ... ``` or just ``` ... ```
- const codeBlockRegex = /```(?:json)?\s*([\s\S]*?)\s*```/i;
- const match = jsonStr.match(codeBlockRegex);
- if (match && match[1]) {
- jsonStr = match[1].trim();
- } else {
- // 2. If no markdown block, try to find the start and end of JSON characters
- // This handles cases where the AI adds introductory or concluding text outside the block
- const firstOpenBrace = jsonStr.indexOf('{');
- const firstOpenBracket = jsonStr.indexOf('[');
-
- let startIndex = -1;
- if (firstOpenBrace !== -1 && (firstOpenBracket === -1 || firstOpenBrace < firstOpenBracket)) {
- startIndex = firstOpenBrace;
- } else if (firstOpenBracket !== -1) {
- startIndex = firstOpenBracket;
- }
- if (startIndex !== -1) {
- const lastCloseBrace = jsonStr.lastIndexOf('}');
- const lastCloseBracket = jsonStr.lastIndexOf(']');
- const endIndex = Math.max(lastCloseBrace, lastCloseBracket);
-
- if (endIndex !== -1 && endIndex > startIndex) {
- jsonStr = jsonStr.substring(startIndex, endIndex + 1);
- }
- }
- }
- try {
- return JSON.parse(jsonStr) as T;
- } catch (error) {
- console.error('[safeParseJson] Failed to parse JSON:', error);
- console.error('[safeParseJson] Original text:', text);
- console.error('[safeParseJson] Extracted string:', jsonStr);
- return null;
- }
- }
|