tool/Analysis/functions/Repair-JsonResponse.ps1
|
function Repair-JsonResponse { <# .SYNOPSIS Repairs common LLM JSON response issues and returns a parsed object. .DESCRIPTION AI models sometimes produce slightly malformed JSON. This function applies a series of repairs to extract and parse the JSON: 1. Strip markdown code fences (```json ... ```) 2. Replace Infinity/NaN with null 3. Fix empty keys ("","key" → "key") 4. Fix double commas (,,) 5. Fix trailing commas before closing braces/brackets 6. Extract JSON object if surrounded by text 7. Parse and return .PARAMETER Response The raw string response from the AI model. .OUTPUTS PSCustomObject — the parsed JSON object. .EXAMPLE $parsed = Repair-JsonResponse -Response $rawResponse #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Response ) if (-not $Response -or $Response.Trim().Length -eq 0) { throw "Empty response — nothing to parse" } $json = $Response # 1. Strip markdown code fences if ($json -match '(?s)^\s*```(?:json)?\s*\n(.+?)\n\s*```\s*$') { $json = $Matches[1] } # 2. Replace Infinity/NaN with null $json = $json -replace '(?<=[\s,:[\{])-?Infinity', 'null' -replace '(?<=[\s,:[\{])NaN', 'null' # 3. Fix stray double-quotes before key names: ,""key" → ,"key" or {""key" → {"key" # This is the Ahmed Samy bug: GPT emits an extra quote creating ""key_name" $json = $json -replace '([,{])""([a-zA-Z_][a-zA-Z0-9_]*)"', '$1"$2"' # 4. Fix empty keys: "","key" → "key" or "": value, "key" → "key" # Pattern: ,"", or "":"...", (empty string key with no proper value) $json = $json -replace ',""\s*,', ',' $json = $json -replace '\{""\s*,', '{' # Pattern: "":"value"," → remove the empty-key pair $json = $json -replace '""\s*:\s*"[^"]*"\s*,', '' # Pattern: ,"":"value"} → } $json = $json -replace ',\s*""\s*:\s*"[^"]*"\s*}', '}' # 5. Fix double/triple commas $json = $json -replace ',\s*,+', ',' # 6. Fix trailing commas before } or ] $json = $json -replace ',\s*([}\]])', '$1' # 7. Extract JSON object if response contains non-JSON prefix/suffix if ($json[0] -ne '{') { if ($json -match '(?s)(\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\})\s*$') { $json = $Matches[1] } elseif ($json -match '(?s)(\{.+\})') { $json = $Matches[1] } else { throw "Response does not contain valid JSON" } } # 8. Parse try { return ($json | ConvertFrom-Json) } catch { # Last resort: try to fix unescaped quotes inside string values # This is aggressive but catches "value with "quotes" inside" throw "JSON parse failed after repair: $($_.Exception.Message)" } } |