| import json |
| import re |
| from typing import Any, Optional |
|
|
| def extract_json_block(text: str) -> str: |
| """ |
| Extract the first continuous JSON-like block (starting with { and ending with }). |
| This helps skip LLM chatter before or after the JSON. |
| """ |
| |
| start = text.find('{') |
| end = text.rfind('}') |
| |
| if start != -1 and end != -1 and end > start: |
| return text[start:end+1] |
| return text |
|
|
| def safe_json_loads(raw: str) -> dict: |
| """ |
| Safely load JSON from a string that may contain: |
| 1. Markdown code blocks (```json ... ```) |
| 2. Prefix/suffix text |
| 3. Unescaped control characters (newlines, tabs) inside strings |
| """ |
| if not raw: |
| return {} |
|
|
| |
| cleaned = re.sub(r"```json|```", "", raw).strip() |
| |
| |
| json_str = extract_json_block(cleaned) |
| |
| try: |
| |
| return json.loads(json_str, strict=False) |
| except json.JSONDecodeError as e: |
| |
| try: |
| |
| |
| |
| |
| raise e |
| except Exception: |
| print(f"Failed to parse JSON: {raw[:200]}...") |
| return {} |
|
|