MCPcopy Index your code
hub / github.com/AI45Lab/Code / try_parse_partial_json

Function try_parse_partial_json

core/src/llm/structured.rs:494–586  ·  view source on GitHub ↗

Attempt to parse a potentially incomplete JSON string into the most complete valid partial object possible. Strategy: try parsing as-is first. If that fails, progressively close open braces/brackets and try again. This handles the common case where the LLM has output `{"name": "foo", "items": [1, 2` — we close it to get a partial.

(text: &str)

Source from the content-addressed store, hash-verified

492/// braces/brackets and try again. This handles the common case where the LLM
493/// has output `{"name": "foo", "items": [1, 2` — we close it to get a partial.
494fn try_parse_partial_json(text: &str) -> Option<Value> {
495 let trimmed = text.trim();
496 if trimmed.is_empty() {
497 return None;
498 }
499
500 // Fast path: already valid
501 if let Ok(v) = serde_json::from_str::<Value>(trimmed) {
502 if v.is_object() || v.is_array() {
503 return Some(v);
504 }
505 }
506
507 // Count unclosed brackets/braces (respecting strings)
508 let mut closers = Vec::new();
509 let mut in_string = false;
510 let mut escape_next = false;
511 // Track if we're mid-value (after a colon or comma, before the value is complete)
512 let mut last_significant: Option<u8> = None;
513
514 for &b in trimmed.as_bytes() {
515 if escape_next {
516 escape_next = false;
517 continue;
518 }
519 match b {
520 b'\\' if in_string => {
521 escape_next = true;
522 }
523 b'"' => {
524 in_string = !in_string;
525 if !in_string {
526 last_significant = Some(b'"');
527 }
528 }
529 _ if in_string => {}
530 b'{' => {
531 closers.push(b'}');
532 last_significant = Some(b'{');
533 }
534 b'[' => {
535 closers.push(b']');
536 last_significant = Some(b'[');
537 }
538 b'}' | b']' => {
539 closers.pop();
540 last_significant = Some(b);
541 }
542 b':' | b',' => {
543 last_significant = Some(b);
544 }
545 b if !b.is_ascii_whitespace() => {
546 last_significant = Some(b);
547 }
548 _ => {}
549 }
550 }
551

Calls 4

popMethod · 0.80
is_emptyMethod · 0.45
lenMethod · 0.45
truncateMethod · 0.45