1use std::collections::HashMap;
2
3pub fn fix(input: impl Into<String>) -> String {
10 let json = Parser::new(input).parse_and_fix();
11 json.deserialize_all().stringify(0)
12}
13
14struct Parser {
15 chars: Vec<char>,
16 i: usize,
17}
18
19impl Parser {
20 pub fn new(input: impl Into<String>) -> Self {
21 Self {
22 chars: input.into().trim().chars().collect(),
23 i: 0,
24 }
25 }
26
27 fn peek(&mut self) -> Option<char> {
28 self.chars.get(self.i).copied()
29 }
30
31 fn next(&mut self) -> Option<char> {
32 let c = self.peek();
33 if c.is_some() {
34 self.i += 1;
35 }
36 c
37 }
38
39 fn skip_whitespace(&mut self) {
40 while let Some(c) = self.peek()
41 && c.is_whitespace()
42 {
43 self.next();
44 }
45 }
46
47 pub fn parse_and_fix(&mut self) -> Json {
48 self.parse_value()
49 }
50
51 fn parse_value(&mut self) -> Json {
52 self.skip_whitespace();
53
54 if let Some(c) = self.peek() {
55 match c {
56 'n' | 'N' | 't' | 'T' | 'f' | 'F' => self.parse_static(),
57
58 val if val.is_ascii_digit() || val == '-' || val == '.' => self.parse_number(),
59
60 '"' => self.parse_string(),
61
62 '[' => self.parse_array(),
63
64 '{' => self.parse_object(),
65
66 _ => {
67 self.next();
68 Json::Null
69 }
70 }
71 } else {
72 Json::Null
73 }
74 }
75
76 fn parse_static(&mut self) -> Json {
77 match self.next().unwrap().to_ascii_lowercase() {
78 'n' => Json::Null,
79 't' => Json::True,
80 _ => Json::False,
81 }
82 }
83
84 fn parse_number(&mut self) -> Json {
85 let mut lex = String::new();
86
87 if let Some('-') = self.peek() {
88 lex.push('-');
89 self.next();
90
91 while let Some('-') = self.peek() {
92 self.next();
93 }
94 }
95
96 if let Some('.') = self.peek() {
97 lex.push('0');
98 }
99
100 if let Some('0') = self.peek() {
102 lex.push('0');
103 self.next();
104
105 while let Some(c) = self.peek() {
106 if c == '0' {
107 self.next();
108 } else {
109 if c.is_ascii_digit() {
110 lex.pop();
111 }
112 break;
113 }
114 }
115 }
116
117 while let Some(c) = self.peek()
119 && c.is_ascii_digit()
120 {
121 lex.push(c);
122 self.next();
123 }
124
125 if let Some('.') = self.peek() {
127 lex.push('.');
128 self.next();
129
130 let mut count = 0;
131 while let Some(c) = self.peek()
132 && c.is_ascii_digit()
133 {
134 lex.push(c);
135 self.next();
136 count += 1;
137 }
138
139 if count == 0 {
140 lex.push('0');
141 }
142 }
143
144 if let Some(c) = self.peek()
146 && (c == 'e' || c == 'E')
147 {
148 lex.push(c);
149 self.next();
150
151 if let Some(sign) = self.peek()
152 && (sign == '-' || sign == '+')
153 {
154 lex.push(sign);
155 self.next();
156 }
157
158 let mut count = 0;
159 while let Some(c) = self.peek()
160 && c.is_ascii_digit()
161 {
162 lex.push(c);
163 self.next();
164 count += 1;
165 }
166
167 if count == 0 {
168 if lex.ends_with('-') || lex.ends_with('+') {
169 lex.pop();
170 }
171 lex.pop();
172 }
173 }
174
175 if lex == "-" {
176 lex.push('0');
177 }
178
179 Json::Number(lex)
180 }
181
182 fn parse_string(&mut self) -> Json {
183 let mut lex = String::new();
184
185 self.next();
186 while let Some(c) = self.next() {
187 match c {
188 '"' => {
189 break;
190 }
191
192 '\\' => {
193 if let Some(esc) = self.next() {
194 match esc {
195 '"' => lex.push('"'),
196 '\\' => lex.push('\\'),
197 '/' => lex.push('/'),
198 'b' => lex.push('\u{0008}'),
199 'f' => lex.push('\u{000C}'),
200 'n' => lex.push('\n'),
201 'r' => lex.push('\r'),
202 't' => lex.push('\t'),
203
204 'u' => {
205 if let Some(c) = self.parse_unicode_escape() {
206 lex.push(c);
207 }
208 }
209
210 ch => {
211 lex.push(ch);
212 }
213 }
214 }
215 }
216
217 _ => {
218 lex.push(c);
219 }
220 }
221 }
222
223 Json::String(lex)
224 }
225
226 fn parse_unicode_escape(&mut self) -> Option<char> {
227 let mut hex = String::new();
228 for _ in 0..4 {
229 if let Some(c) = self.next() {
230 hex.push(c);
231 } else {
232 return None;
233 }
234 }
235
236 let code = u32::from_str_radix(&hex, 16).ok()?;
237
238 if let Some(ch) = char::from_u32(code) {
239 Some(ch)
240 } else if (0xD800..=0xDBFF).contains(&code) {
241 if let (Some('\\'), Some('u')) = (self.next(), self.next()) {
242 let mut low_hex = String::new();
243 for _ in 0..4 {
244 if let Some(c) = self.next() {
245 low_hex.push(c);
246 } else {
247 return None;
248 }
249 }
250
251 let low_code = u32::from_str_radix(&low_hex, 16).ok()?;
252
253 if (0xDC00..=0xDFFF).contains(&low_code) {
254 let full_code = 0x10000 + ((code - 0xD800) << 10) + (low_code - 0xDC00);
255
256 char::from_u32(full_code)
257 } else {
258 None
259 }
260 } else {
261 None
262 }
263 } else {
264 None
265 }
266 }
267
268 fn parse_array(&mut self) -> Json {
269 let mut arr = Vec::new();
270
271 self.next();
272
273 loop {
274 self.skip_whitespace();
275
276 match self.peek() {
277 Some(']') => {
278 self.next();
279 break;
280 }
281
282 Some(',') => {
283 self.next();
284 continue;
285 }
286
287 Some(_) => {
288 arr.push(self.parse_value());
289
290 self.skip_whitespace();
291
292 while let Some(c) = self.peek() {
293 match c {
294 ']' | ',' => {
295 break;
296 }
297
298 _ => {
299 self.next();
300 }
301 }
302 }
303 }
304
305 None => {
306 break;
307 }
308 }
309 }
310
311 Json::Array(arr)
312 }
313
314 fn parse_object(&mut self) -> Json {
315 let mut obj = HashMap::new();
316 let mut order = Vec::new();
317
318 self.next();
319
320 loop {
321 self.skip_whitespace();
322
323 match self.peek() {
324 Some('}') => {
325 self.next();
326 break;
327 }
328
329 Some('"') => {
330 let key = match self.parse_string() {
331 Json::String(s) => s,
332 _ => unreachable!(),
333 };
334
335 self.skip_whitespace();
336
337 if self.peek() == Some(':') {
338 self.next();
339 }
340
341 if obj.contains_key(&key)
342 && let Some(pos) = order.iter().position(|k| k == &key)
343 {
344 order.remove(pos);
345 }
346
347 obj.insert(key.clone(), self.parse_value());
348 order.push(key);
349 }
350
351 None => {
352 break;
353 }
354
355 _ => {
356 self.next();
357 }
358 }
359 }
360
361 Json::Object((obj, order))
362 }
363}
364
365fn escape_string(s: &str) -> String {
366 let mut result = String::with_capacity(s.len());
367 for c in s.chars() {
368 match c {
369 '"' => result.push_str("\\\""),
370 '\\' => result.push_str("\\\\"),
371 '\n' => result.push_str("\\n"),
372 '\r' => result.push_str("\\r"),
373 '\t' => result.push_str("\\t"),
374 '\u{0008}' => result.push_str("\\b"),
375 '\u{000C}' => result.push_str("\\f"),
376 ch if ch < ' ' => {
377 result.push_str(&format!("\\u{:04x}", ch as u32));
378 }
379 ch => result.push(ch),
380 }
381 }
382 result
383}
384
385enum Json {
386 Null,
387 True,
388 False,
389 Number(String),
390 String(String),
391 Array(Vec<Json>),
392 Object((HashMap<String, Json>, Vec<String>)),
393}
394
395impl Json {
396 pub fn deserialize_all(self) -> Json {
397 match self {
398 Self::String(val) => {
399 let trimmed = val.trim();
400
401 if trimmed.starts_with('{') || trimmed.starts_with('[') {
402 Parser::new(trimmed).parse_and_fix().deserialize_all()
403 } else {
404 Json::String(val)
405 }
406 }
407
408 Json::Array(arr) => Json::Array(arr.into_iter().map(|v| v.deserialize_all()).collect()),
409
410 Json::Object((obj, order)) => Json::Object((
411 obj.into_iter()
412 .map(|(k, v)| (k, v.deserialize_all()))
413 .collect(),
414 order,
415 )),
416
417 other => other,
418 }
419 }
420
421 pub fn stringify(&self, tabs: usize) -> String {
422 const TAB: &str = " ";
423
424 match self {
425 Self::Null => "null".to_string(),
426 Self::True => "true".to_string(),
427 Self::False => "false".to_string(),
428
429 Self::Number(val) => val.clone(),
430 Self::String(val) => format!("\"{}\"", escape_string(val)),
431
432 Self::Array(arr) => {
433 if arr.is_empty() {
434 return "[]".to_string();
435 }
436
437 let mut result = String::from("[\n");
438 let tab_str = TAB.repeat(tabs + 1);
439
440 for val in arr {
441 result.push_str(&format!("{}{},\n", tab_str, val.stringify(tabs + 1)));
442 }
443
444 result.truncate(result.len() - 2);
445
446 result.push('\n');
447 result.push_str(&TAB.repeat(tabs));
448 result.push(']');
449 result
450 }
451
452 Self::Object((obj, order)) => {
453 if obj.is_empty() {
454 return "{}".to_string();
455 }
456
457 let mut result = String::from("{\n");
458 let tab_str = TAB.repeat(tabs + 1);
459
460 for key in order {
461 if let Some(val) = obj.get(key) {
462 result.push_str(&format!(
463 "{}\"{}\": {},\n",
464 tab_str,
465 escape_string(key),
466 val.stringify(tabs + 1)
467 ));
468 }
469 }
470
471 result.truncate(result.len() - 2);
472
473 result.push('\n');
474 result.push_str(&TAB.repeat(tabs));
475 result.push('}');
476 result
477 }
478 }
479 }
480}
481
482#[cfg(test)]
483mod tests;