This commit is contained in:
team3
2026-07-12 16:13:50 +02:00
parent a284e03225
commit 31a42bbf1d
48 changed files with 3625 additions and 253 deletions

View File

@@ -8,14 +8,25 @@ _FENCE = re.compile(r"```(?:json)?\s*(.*?)```", re.DOTALL)
def parse(text: str):
"""→ Objekt oder None. Nie werfen — der Aufrufer entscheidet über Retry."""
"""→ Objekt oder None. Nie werfen — der Aufrufer entscheidet über Retry.
Jeden Code-Fence UND den Gesamttext durchprobieren; erster Treffer gewinnt.
(Nur den ersten Fence zu nehmen verlor JSON, das nach einem Prosa-Beispiel-
Fence stand.)"""
if not text:
return None
for kandidat in [m.group(1) for m in _FENCE.finditer(text)] + [text]:
daten = _ein_kandidat(kandidat.strip())
if daten is not None:
return daten
return None
def _ein_kandidat(text: str):
"""Erstes vollständiges JSON-Objekt/-Array in `text` (Klammer-Balance) oder
None. Das FRÜHESTE Klammerzeichen entscheidet — sonst gewinnt ein {…} im
Array-Inneren."""
if not text:
return None
m = _FENCE.search(text)
if m:
text = m.group(1)
text = text.strip()
# Das FRÜHESTE Klammerzeichen entscheidet: sonst gewinnt ein {…} im Array-Inneren.
erste = sorted((("{", "}"), ("[", "]")),
key=lambda p: text.find(p[0]) if p[0] in text else len(text))
for start_ch, end_ch in erste: