alchemy_llm/utils/
json_parse.rs1use serde_json::Value;
7
8pub fn parse_streaming_json(s: &str) -> Value {
35 if let Ok(v) = serde_json::from_str(s) {
37 return v;
38 }
39
40 let completions = ["}", "}}", "\"}", "\"}}", "null}", "null}}", "]}", "]}}"];
42
43 for suffix in completions {
44 let attempt = format!("{}{}", s, suffix);
45 if let Ok(v) = serde_json::from_str(&attempt) {
46 return v;
47 }
48 }
49
50 Value::Object(Default::default())
52}
53
54pub fn parse_streaming_json_smart(s: &str) -> Value {
71 if let Ok(v) = serde_json::from_str(s) {
73 return v;
74 }
75
76 let mut stack: Vec<char> = Vec::new();
78 let mut in_string = false;
79 let mut escape_next = false;
80
81 for c in s.chars() {
82 if escape_next {
83 escape_next = false;
84 continue;
85 }
86
87 match c {
88 '\\' if in_string => escape_next = true,
89 '"' => in_string = !in_string,
90 '{' if !in_string => stack.push('{'),
91 '}' if !in_string => {
92 if stack.last() == Some(&'{') {
93 stack.pop();
94 }
95 }
96 '[' if !in_string => stack.push('['),
97 ']' if !in_string => {
98 if stack.last() == Some(&'[') {
99 stack.pop();
100 }
101 }
102 _ => {}
103 }
104 }
105
106 let mut completion = String::new();
108
109 if in_string {
111 completion.push('"');
112 }
113
114 for opener in stack.iter().rev() {
116 match opener {
117 '{' => completion.push('}'),
118 '[' => completion.push(']'),
119 _ => {}
120 }
121 }
122
123 let attempt = format!("{}{}", s, completion);
124 serde_json::from_str(&attempt).unwrap_or_else(|_| Value::Object(Default::default()))
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use serde_json::json;
131
132 #[test]
133 fn test_complete_json() {
134 let result = parse_streaming_json(r#"{"name": "test"}"#);
135 assert_eq!(result, json!({"name": "test"}));
136 }
137
138 #[test]
139 fn test_missing_closing_brace() {
140 let result = parse_streaming_json(r#"{"name": "test""#);
141 assert_eq!(result, json!({"name": "test"}));
142 }
143
144 #[test]
145 fn test_nested_missing_braces() {
146 let result = parse_streaming_json(r#"{"outer": {"inner": 1"#);
147 assert_eq!(result, json!({"outer": {"inner": 1}}));
148 }
149
150 #[test]
151 fn test_empty_input() {
152 let result = parse_streaming_json("");
153 assert_eq!(result, json!({}));
154 }
155
156 #[test]
157 fn test_with_number_value() {
158 let result = parse_streaming_json(r#"{"count": 42"#);
159 assert_eq!(result, json!({"count": 42}));
160 }
161
162 #[test]
163 fn test_with_null_value() {
164 let result = parse_streaming_json(r#"{"value": null}"#);
165 assert_eq!(result, json!({"value": null}));
166 }
167
168 #[test]
169 fn test_incomplete_string_value() {
170 let result = parse_streaming_json(r#"{"name": "test"#);
172 assert!(result.is_object());
174 }
175
176 #[test]
177 fn test_smart_parser_complete() {
178 let result = parse_streaming_json_smart(r#"{"name": "test"}"#);
179 assert_eq!(result, json!({"name": "test"}));
180 }
181
182 #[test]
183 fn test_smart_parser_array() {
184 let result = parse_streaming_json_smart(r#"{"items": [1, 2, 3"#);
185 assert_eq!(result, json!({"items": [1, 2, 3]}));
186 }
187
188 #[test]
189 fn test_smart_parser_nested() {
190 let result = parse_streaming_json_smart(r#"{"a": {"b": {"c": 1"#);
191 assert_eq!(result, json!({"a": {"b": {"c": 1}}}));
192 }
193
194 #[test]
195 fn test_smart_parser_mixed() {
196 let result = parse_streaming_json_smart(r#"{"list": [{"id": 1}, {"id": 2"#);
197 assert_eq!(result, json!({"list": [{"id": 1}, {"id": 2}]}));
198 }
199
200 #[test]
201 fn test_smart_parser_unclosed_string() {
202 let result = parse_streaming_json_smart(r#"{"name": "test"#);
203 assert_eq!(result, json!({"name": "test"}));
205 }
206
207 #[test]
208 fn test_smart_parser_escaped_quotes() {
209 let result = parse_streaming_json_smart(r#"{"text": "hello \"world\""}"#);
210 assert_eq!(result, json!({"text": "hello \"world\""}));
211 }
212
213 #[test]
214 fn test_smart_parser_deeply_nested() {
215 let result = parse_streaming_json_smart(r#"{"a": [{"b": [{"c": 1"#);
216 assert_eq!(result, json!({"a": [{"b": [{"c": 1}]}]}));
217 }
218
219 #[test]
220 fn test_smart_parser_empty() {
221 let result = parse_streaming_json_smart("");
222 assert_eq!(result, json!({}));
223 }
224
225 #[test]
226 fn test_smart_parser_just_brace() {
227 let result = parse_streaming_json_smart("{");
228 assert_eq!(result, json!({}));
229 }
230
231 #[test]
232 fn test_smart_parser_partial_key() {
233 let result = parse_streaming_json_smart(r#"{"na"#);
235 assert!(result.is_object());
237 }
238}