{
  "nodes": [
    {
      "id": "4fd2662b-6698-4ec2-9b27-97afaa3416c1",
      "name": "Robust JSON Parser",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -432,
        -64
      ],
      "parameters": {
        "inputSource": "jsonExample",
        "jsonExample": "{\n  \"text\": \"{\\\"your\\\": \\\"json to parse goes here\\\"}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "a8e7b7d4-ff0f-4138-8b7e-b01900b1013f",
      "name": "Safe JSON Parser",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        272,
        -64
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "/**\n * Escapes control characters (like \\n, \\r, \\t) within JSON strings.\n * Ex: Replaces a literal newline in \"hello\\nworld\" with \"hello\\\\nworld\".\n * @param {string} jsonString The string potentially containing unescaped control characters.\n * @returns {string} The corrected string.\n */\nfunction escapeControlCharsInStrings(jsonString) {\n    let fixed = \"\";\n    let inString = false;\n    let escapeNext = false;\n\n    for (let i = 0; i < jsonString.length; i++) {\n        const char = jsonString[i];\n\n        if (escapeNext) {\n            fixed += char;\n            escapeNext = false;\n            continue;\n        }\n\n        if (char === '\\\\') {\n            fixed += '\\\\';\n            escapeNext = true;\n            continue;\n        }\n\n        if (char === '\"') {\n            fixed += '\"';\n            inString = !inString;\n            continue;\n        }\n\n        if (inString) {\n            if (char === '\\n') {\n                fixed += '\\\\n';\n            } else if (char === '\\r') {\n                fixed += '\\\\r';\n            } else if (char === '\\t') {\n                fixed += '\\\\t';\n            } else if (char === '\\b') {\n                fixed += '\\\\b';\n            } else if (char === '\\f') {\n                fixed += '\\\\f';\n            }\n            // Handle other control characters (U+0000 to U+001F)\n            // that do not have a short escape sequence.\n            else if (char.charCodeAt(0) >= 0 && char.charCodeAt(0) <= 31) {\n                let hex = char.charCodeAt(0).toString(16);\n                fixed += '\\\\u' + '0000'.substring(hex.length) + hex;\n            }\n            else {\n                fixed += char;\n            }\n        } else {\n            fixed += char;\n        }\n    }\n    return fixed;\n}\n\n\n/**\n * Fixes invalid escape sequences in a potential JSON string\n * by escaping the backslash itself.\n * Ex: Replaces `\\$` with `\\\\$`, `\\: ` with `\\\\:`, but leaves `\\\"` or `\\\\` or `\\n` (if already escaped) intact.\n * @param {string} jsonString The string potentially containing invalid escapes.\n * @returns {string} The corrected string.\n */\nfunction fixInvalidEscapes(jsonString) {\n    let fixed = \"\";\n    for (let i = 0; i < jsonString.length; i++) {\n        if (jsonString[i] === '\\\\') {\n            if (i + 1 < jsonString.length) {\n                const nextChar = jsonString[i + 1];\n                const validEscapeChars = ['\"', '\\\\', '/', 'b', 'f', 'n', 'r', 't'];\n\n                if (validEscapeChars.includes(nextChar)) {\n                    fixed += '\\\\' + nextChar;\n                    i++;\n                } else if (nextChar === 'u') {\n                    if (i + 5 < jsonString.length && /^[0-9a-fA-F]{4}$/.test(jsonString.substring(i + 2, i + 6))) {\n                        fixed += '\\\\u' + jsonString.substring(i + 2, i + 6);\n                        i += 5;\n                    } else {\n                        fixed += '\\\\\\\\u';\n                        i++;\n                    }\n                } else {\n                    fixed += '\\\\\\\\' + nextChar;\n                    i++;\n                }\n            } else {\n                fixed += '\\\\\\\\';\n            }\n        } else {\n            fixed += jsonString[i];\n        }\n    }\n    return fixed;\n}\n\n/**\n * Attempts to parse a JSON string. Returns the object/array or null on error.\n * Also captures the error message with context.\n * @param {string} jsonString The string to parse.\n * @returns {{ data: object | Array | null, error: string | null }} Parsing result.\n */\nfunction tryParseJsonInternal(jsonString) {\n    try {\n        const data = JSON.parse(jsonString);\n        if (typeof data === 'object' && data !== null) {\n            return { data: data, error: null };\n        } else {\n            return { data: null, error: \"Parsed data is not a JSON object or array.\" };\n        }\n    } catch (e) {\n        let errorMessage = e.message;\n        if (e.message.includes('position')) {\n             try {\n                 const positionMatch = e.message.match(/position\\s+(\\d+)/);\n                 if (positionMatch && positionMatch[1]) {\n                      const position = parseInt(positionMatch[1], 10);\n                      const contextChars = 20;\n                      const start = Math.max(0, position - contextChars);\n                      const end = Math.min(jsonString.length, position + contextChars);\n                      const context = jsonString.substring(start, end);\n                      errorMessage += ` (near: ...${context}...)`;\n                 }\n             } catch (contextError) { /* Ignore error during context generation */ }\n        }\n        return { data: null, error: errorMessage };\n    }\n}\n\n\n/**\n * Attempts to fix unescaped double quotes within JSON strings.\n * @param {string} jsonString The potentially malformed JSON string.\n * @returns {string} The JSON string with an attempted quote fix.\n */\nfunction fixJsonStringQuotes(jsonString) {\n    let fixed = \"\";\n    let inString = false;\n    let escapeNext = false;\n\n    for (let i = 0; i < jsonString.length; i++) {\n        const char = jsonString[i];\n\n        if (escapeNext) { fixed += char; escapeNext = false; continue; }\n        if (char === '\\\\') { fixed += '\\\\'; escapeNext = true; continue; }\n        if (char === '\"') {\n            if (inString) {\n                let nextMeaningfulChar = null;\n                for (let j = i + 1; j < jsonString.length; j++) {\n                    if (!/\\s/.test(jsonString[j])) { nextMeaningfulChar = jsonString[j]; break; }\n                }\n                if (nextMeaningfulChar === null || [':', ',', '}', ']'].includes(nextMeaningfulChar)) {\n                    fixed += '\"'; inString = false;\n                } else { fixed += '\\\\\"'; } // Escape internal quote\n            } else { fixed += '\"'; inString = true; }\n        } else { fixed += char; }\n    }\n    return fixed;\n}\n\n\n/**\n * Extracts potential JSON objects or arrays based on balancing { } and [ ] characters.\n * @param {string} text The source text.\n * @returns {string[]} An array of potentially JSON strings.\n */\nfunction extractPotentialJsonStrings(text) {\n    const results = [];\n    let braceDepth = 0, bracketDepth = 0, startIndex = -1, inString = false, escapeNext = false;\n    for (let i = 0; i < text.length; i++) {\n        const char = text[i];\n        if (escapeNext) { escapeNext = false; continue; }\n        if (char === '\\\\') { escapeNext = true; continue; }\n        if (char === '\"') { inString = !inString; }\n        if (!inString) {\n            if (char === '{') { if (braceDepth === 0 && bracketDepth === 0) startIndex = i; braceDepth++; }\n            else if (char === '}') { if (braceDepth > 0) { braceDepth--; if (braceDepth === 0 && bracketDepth === 0 && startIndex !== -1) { results.push(text.substring(startIndex, i + 1)); startIndex = -1; } } }\n            else if (char === '[') { if (braceDepth === 0 && bracketDepth === 0) startIndex = i; bracketDepth++; }\n            else if (char === ']') { if (bracketDepth > 0) { bracketDepth--; if (braceDepth === 0 && bracketDepth === 0 && startIndex !== -1) { results.push(text.substring(startIndex, i + 1)); startIndex = -1; } } }\n        }\n    }\n    return results;\n}\n\n/**\n * Attempts to fix trailing commas.\n * @param {string} jsonString JSON string potentially with trailing commas.\n * @returns {string} Corrected string.\n */\nfunction fixTrailingCommas(jsonString) {\n    try { return jsonString.replace(/,\\s*([}\\]])/g, '$1'); }\n    catch(e) { return jsonString; }\n}\n\n/**\n * Main function to find and parse the first valid JSON object/array in a text,\n * with pre-cleaning and multiple correction attempts.\n * Merges the keys of the found JSON with parsing metadata.\n *\n * @param {string} text The text potentially containing JSON.\n * @returns {object} An object containing the keys of the parsed JSON (if object)\n *                   or a 'parsed_data' key (if array), and a 'parsing_status' object.\n */\nfunction findAndParseJsonRobustly(text) {\n    let firstParsedData = null;\n    const parsing_status = {\n        success: false,\n        successfulMethod: null,\n        controlCharFixApplied: false, // New flag\n        invalidEscapeFixApplied: false,\n        trailingCommaFixApplied: false,\n        quoteFixApplied: false,\n        parsingLog: [],\n        errors: [],\n        originalInput: text,\n        cleanedInput: null,\n        finalAttemptedJsonString: null\n    };\n\n    if (!text || typeof text !== 'string') {\n        parsing_status.errors.push(\"Input text is null or not a string.\");\n        parsing_status.parsingLog.push(\"Validation failed: Input is not a valid string.\");\n        return { parsing_status };\n    }\n\n    parsing_status.parsingLog.push(\"Starting robust JSON parsing.\");\n\n    let currentText = text.trim();\n    parsing_status.parsingLog.push(`Original length: ${text.length}, Trimmed length: ${currentText.length}`);\n    const markdownBlockRegex = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/;\n    const match = currentText.match(markdownBlockRegex);\n    if (match && match[1]) {\n        currentText = match[1].trim();\n        parsing_status.parsingLog.push(\"Detected and removed Markdown code block fences.\");\n    } else {\n        parsing_status.parsingLog.push(\"No Markdown code block fences detected.\");\n    }\n    parsing_status.cleanedInput = currentText;\n    parsing_status.parsingLog.push(`Cleaned text length after potential fence removal: ${currentText.length}`);\n\n    function processSuccess(data, method, flags) {\n        parsing_status.parsingLog.push(`Success with method: ${method}`);\n        parsing_status.success = true;\n        parsing_status.successfulMethod = method;\n        parsing_status.controlCharFixApplied = flags.controlCharFixApplied || false;\n        parsing_status.invalidEscapeFixApplied = flags.invalidEscapeFixApplied || false;\n        parsing_status.trailingCommaFixApplied = flags.trailingCommaFixApplied || false;\n        parsing_status.quoteFixApplied = flags.quoteFixApplied || false;\n        firstParsedData = data;\n    }\n\n    function attemptParseAndFix(textToParse, baseMethodName) {\n        let currentAttemptText = textToParse;\n        let flags = { controlCharFixApplied: false, invalidEscapeFixApplied: false, trailingCommaFixApplied: false, quoteFixApplied: false };\n        let method = baseMethodName;\n        let parseResult;\n\n        // 0. Escape control characters WITHIN strings (BEFORE fixInvalidEscapes)\n        parsing_status.parsingLog.push(`[${baseMethodName}] Applying control character escaping in strings...`);\n        let fixedControlCharsText = escapeControlCharsInStrings(currentAttemptText);\n        if (fixedControlCharsText !== currentAttemptText) {\n            parsing_status.parsingLog.push(`[${baseMethodName}] Control characters in strings escaped.`);\n            flags.controlCharFixApplied = true;\n            currentAttemptText = fixedControlCharsText;\n            method = `${baseMethodName} + Control Char Escape`;\n        } else {\n            parsing_status.parsingLog.push(`[${baseMethodName}] No control characters in strings needed escaping or found.`);\n        }\n        parsing_status.finalAttemptedJsonString = currentAttemptText;\n        parseResult = tryParseJsonInternal(currentAttemptText);\n        if (parseResult.data) { processSuccess(parseResult.data, method, flags); return true; }\n        parsing_status.parsingLog.push(`[${baseMethodName}] Parse failed after control char escape (if any): ${parseResult.error}`);\n        parsing_status.errors.push(`Parse (${method}): ${parseResult.error}`);\n\n\n        // 1. Fix invalid escapes (backslash)\n        parsing_status.parsingLog.push(`[${baseMethodName}] Applying invalid escape fix (escaping backslash)...`);\n        let fixedEscapesText = fixInvalidEscapes(currentAttemptText);\n        if (fixedEscapesText !== currentAttemptText) {\n            parsing_status.parsingLog.push(`[${baseMethodName}] Invalid backslash escapes fixed.`);\n            flags.invalidEscapeFixApplied = true;\n            currentAttemptText = fixedEscapesText;\n            method = `${baseMethodName}${flags.controlCharFixApplied ? ' + Control Char Escape' : ''} + Invalid Escape Fix`;\n        } else {\n            parsing_status.parsingLog.push(`[${baseMethodName}] No invalid backslash escapes found/fixed.`);\n        }\n        parsing_status.finalAttemptedJsonString = currentAttemptText;\n        parseResult = tryParseJsonInternal(currentAttemptText);\n        if (parseResult.data) { processSuccess(parseResult.data, method, flags); return true; }\n        parsing_status.parsingLog.push(`[${baseMethodName}] Parse failed after invalid escape fix (if any): ${parseResult.error}`);\n        parsing_status.errors.push(`Parse (${method}): ${parseResult.error}`);\n\n\n        // 2. Fix trailing commas\n        parsing_status.parsingLog.push(`[${baseMethodName}] Applying trailing comma fix...`);\n        let fixedCommasText = fixTrailingCommas(currentAttemptText);\n        if (fixedCommasText !== currentAttemptText) {\n            parsing_status.parsingLog.push(`[${baseMethodName}] Trailing commas fixed.`);\n            flags.trailingCommaFixApplied = true;\n            currentAttemptText = fixedCommasText;\n            method = `${baseMethodName}${flags.controlCharFixApplied ? ' + Control Char Escape' : ''}${flags.invalidEscapeFixApplied ? ' + Invalid Escape Fix' : ''} + Trailing Comma Fix`;\n            parsing_status.finalAttemptedJsonString = currentAttemptText;\n            parseResult = tryParseJsonInternal(currentAttemptText);\n            if (parseResult.data) { processSuccess(parseResult.data, method, flags); return true; }\n            parsing_status.parsingLog.push(`[${baseMethodName}] Parse failed after comma fix: ${parseResult.error}`);\n            parsing_status.errors.push(`Parse (${method}): ${parseResult.error}`);\n        } else {\n            parsing_status.parsingLog.push(`[${baseMethodName}] No trailing commas found/fixed.`);\n        }\n\n        // 3. Fix quotes\n        parsing_status.parsingLog.push(`[${baseMethodName}] Applying quote fix...`);\n        try {\n            let fixedQuotesText = fixJsonStringQuotes(currentAttemptText);\n            if (fixedQuotesText !== currentAttemptText) {\n                parsing_status.parsingLog.push(`[${baseMethodName}] Quotes fixed.`);\n                flags.quoteFixApplied = true;\n                currentAttemptText = fixedQuotesText;\n                method = `${baseMethodName}${flags.controlCharFixApplied ? ' + Control Char Escape' : ''}${flags.invalidEscapeFixApplied ? ' + Invalid Escape Fix' : ''}${flags.trailingCommaFixApplied ? ' + Trailing Comma Fix' : ''} + Quote Fix`;\n                parsing_status.finalAttemptedJsonString = currentAttemptText;\n                parseResult = tryParseJsonInternal(currentAttemptText);\n                if (parseResult.data) { processSuccess(parseResult.data, method, flags); return true; }\n                parsing_status.parsingLog.push(`[${baseMethodName}] Parse failed after quote fix: ${parseResult.error}`);\n                parsing_status.errors.push(`Parse (${method}): ${parseResult.error}`);\n            } else {\n                parsing_status.parsingLog.push(`[${baseMethodName}] Quote fixing did not modify the text.`);\n            }\n        } catch (e) {\n            parsing_status.parsingLog.push(`[${baseMethodName}] Error during quote fixing attempt: ${e.message}`);\n            parsing_status.errors.push(`Parse (${method} - quote fix error): ${e.message}`);\n        }\n        \n        parsing_status.finalAttemptedJsonString = currentAttemptText;\n        return false;\n    }\n\n    parsing_status.parsingLog.push(\"Attempting parse/fix on entire cleaned text...\");\n    attemptParseAndFix(parsing_status.cleanedInput, \"Direct\");\n\n    if (!firstParsedData) {\n        parsing_status.parsingLog.push(\"Direct processing failed. Attempting structured extraction...\");\n        const candidates = extractPotentialJsonStrings(parsing_status.cleanedInput);\n        parsing_status.parsingLog.push(`Found ${candidates.length} potential JSON candidate(s) via balancing.`);\n\n        for (let i = 0; i < candidates.length && !firstParsedData; i++) {\n            const candidate = candidates[i];\n            parsing_status.parsingLog.push(`Attempting parse/fix on candidate ${i + 1}/${candidates.length}...`);\n            attemptParseAndFix(candidate, `Structured Candidate ${i + 1}`);\n        }\n    }\n\n    if (firstParsedData) {\n        parsing_status.parsingLog.push(`Successfully parsed JSON found using method: ${parsing_status.successfulMethod}.`);\n        if (typeof firstParsedData === 'object' && !Array.isArray(firstParsedData)) {\n             return { ...firstParsedData, parsing_status: parsing_status };\n        } else {\n             parsing_status.parsingLog.push(\"Parsed data is an array or non-object, returning under 'parsed_data' key.\");\n             return { parsed_data: firstParsedData, parsing_status: parsing_status };\n        }\n    } else {\n        parsing_status.parsingLog.push(\"No valid JSON object or array could be parsed from the input after all attempts.\");\n        parsing_status.success = false;\n        if (!parsing_status.finalAttemptedJsonString && parsing_status.cleanedInput) {\n             parsing_status.finalAttemptedJsonString = parsing_status.cleanedInput;\n        } else if (!parsing_status.finalAttemptedJsonString) {\n             parsing_status.finalAttemptedJsonString = text;\n        }\n        return { parsing_status: parsing_status };\n    }\n}\n\n// --- n8n Usage ---\nconst inputItem = $input.item.json; \nconst inputText = inputItem && inputItem.text ? inputItem.text : null;\nconst parsingResult = findAndParseJsonRobustly(inputText);\n\nreturn parsingResult;"
      },
      "typeVersion": 2
    },
    {
      "id": "680ea730-fc1f-40d8-91e9-0ea06b09d472",
      "name": "Remove parsing_status",
      "type": "n8n-nodes-base.set",
      "position": [
        672,
        -64
      ],
      "parameters": {
        "include": "except",
        "options": {},
        "excludeFields": "parsing_status",
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "9a42c258-cbb3-4c56-9b6e-53bd77b0f207",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -336
      ],
      "parameters": {
        "color": 7,
        "width": 360,
        "height": 440,
        "content": "#### \u2699\ufe0f OUTPUT CLEANUP\n\nThis node removes the detailed `parsing_status` object from the final output to keep it clean.\n\n**Want to see the full parsing log for debugging?**\n\n\u27a1\ufe0f **Just deactivate or delete this node.**\n\nYou will then get the full output from the parser, including the `parsing_status` object which shows every step and fix that was applied."
      },
      "typeVersion": 1
    },
    {
      "id": "c71da6a1-7553-4c3c-b17a-9a5eecc02552",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        -336
      ],
      "parameters": {
        "color": 7,
        "width": 360,
        "height": 440,
        "content": "#### \u25b6\ufe0f INPUT NODE\n\nThis workflow expects an input item with a `text` field. The value of this field should be the **string** you want to parse.\n\n**Example Input:**\n```json\n{\n  \"text\": \"Some text from an AI... {\\\\\\\"key\\\\\\\": \\\\\\\"value with an unescaped \\\\\\\"quote\\\\\\\" inside\\\\\\\"}\"\n}"
      },
      "typeVersion": 1
    },
    {
      "id": "b5f8dc12-5092-42ba-bb50-47f760418ca8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        -528
      ],
      "parameters": {
        "color": 6,
        "width": 480,
        "height": 620,
        "content": "#### \ud83e\udde0 CORE LOGIC: The Parser\n\nThis node contains all the logic for cleaning and parsing the input string. It does not need to be edited for normal use.\n\n**Process Overview:**\n1.  **Cleans Input:** Removes Markdown fences (```) and trims whitespace.\n2.  **Applies Fixes in Order:**\n    *   Escapes control characters (`\\n`, `\\t`) inside strings.\n    *   Fixes invalid backslashes (e.g., `\\\"` -> `\\\\\"`).\n    *   Removes trailing commas.\n    *   Attempts to fix unescaped quotes within values.\n3.  **Parses:** Tries to parse the cleaned string. If it fails, it looks for a `{...}` or `[...]` block within the text and tries again.\n\n\n**Output:**\n*   The successfully parsed JSON fields.\n*   A `parsing_status` object with detailed logs and debugging info."
      },
      "typeVersion": 1
    },
    {
      "id": "e54cafca-18cf-40de-8cce-0fd7ec9e428b",
      "name": "Convert to JSON",
      "type": "n8n-nodes-base.set",
      "onError": "continueErrorOutput",
      "position": [
        -144,
        -64
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ $json.text.replace(/^```json\\s*|\\s*```$/g, '') }}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "140f3f24-935b-4f0c-bad4-8ffdda34da74",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1024,
        -608
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 704,
        "content": "## \ud83d\udee0\ufe0f Process AI Output to Structured JSON with Robust JSON Parser\n\nStop AI hallucinations from breaking your flows by automatically cleaning and repairing malformed JSON output.\n\n### How it works\n\n*   **Markdown Cleanup**: Removes the ` ```json ` code blocks often returned by LLMs.\n*   **Auto-Repair**: Uses a script to fix common errors like unescaped quotes, bad escapes, or trailing commas.\n*   **Clean Output**: Returns a validated JSON object ready for your next nodes.\n\n### Automate your operations today\nYour time is valuable. Let us automate the boring stuff for you.\n\n\n**\ud83d\udc47 CHOOSE YOUR PATH:**\n\n[ **\u26a1\ufe0f I WANT A FREE AUDIT (2 min)** ](https://workflows.ac/audit?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=process_ai_output_to_structured_json_with_robust_json_parser&utm_content=5146)\n> *We've put our heart into this business evaluation machine.*\n\n[ **\ud83d\udca1 I HAVE A SPECIFIC REQUEST** ](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=process_ai_output_to_structured_json_with_robust_json_parser&utm_content=5146)\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0641599d-9712-4b9c-9177-ec6e367db75c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -1008
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 1104,
        "content": "---\n\n## Was this helpful? Let me know!\n[![clic](https://supastudio.ia2s.app/storage/v1/object/public/assets/n8n/clic_down_lucas.gif)](https://api.ia2s.app/form/templates/academy)\n\nI really hope this template helped you. Your feedback is what helps me create better resources for the n8n community.\n\n### **Have Feedback, a Question, or a Project Idea?**\n\n\n#### \u27a1\ufe0f **[Click here to go to the Contact Form](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=process_ai_output_to_structured_json_with_robust_json_parser&utm_content=5146)**\n\nUse this single link for anything you need:\n\n*   **Give Feedback:** Share your thoughts on this template, whether you found a typo, encountered an unexpected error, have a suggestion, or just want to say thanks!\n\n*   **Automation Coaching:** Get personalized, one-on-one guidance to master n8n. We can work together to help you reach an expert level.\n\n*   **Automation Consulting:** Have a complex business challenge or need custom workflows built from scratch? We offer a plug and play automation department for 8 to 88 people teams with unlimited automation requests.\n\n---\n\nHappy Automating!\nLucas Peyrin | [Workflows Accelerator](https://workflows.ac?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=process_ai_output_to_structured_json_with_robust_json_parser&utm_content=5146)"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Convert to JSON": {
      "main": [
        [],
        [
          {
            "node": "Safe JSON Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Safe JSON Parser": {
      "main": [
        [
          {
            "node": "Remove parsing_status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Robust JSON Parser": {
      "main": [
        [
          {
            "node": "Convert to JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}