Skip to main content

jsonc_parser/
serde.rs

1use std::borrow::Cow;
2use std::cell::Cell;
3
4use ::serde::de::DeserializeSeed;
5use ::serde::de::EnumAccess;
6use ::serde::de::IntoDeserializer;
7use ::serde::de::MapAccess;
8use ::serde::de::SeqAccess;
9use ::serde::de::VariantAccess;
10use ::serde::de::Visitor;
11use ::serde::forward_to_deserialize_any;
12
13use super::ParseOptions;
14use super::common::Range;
15use super::errors::ParseError;
16use super::errors::ParseErrorKind;
17use super::tokens::Token;
18use crate::parser::JsoncParser;
19
20/// Parses a string containing JSONC to a `serde_json::Value` or any
21/// type that implements `serde::Deserialize`.
22///
23/// Requires the "serde" cargo feature:
24///
25/// ```toml
26/// jsonc-parser = { version = "...", features = ["serde"] }
27/// ```
28///
29/// # Example
30///
31/// Parsing to a `serde_json::Value`:
32///
33/// ```rs
34/// use jsonc_parser::parse_to_serde_value;
35///
36/// let json_value: serde_json::Value = parse_to_serde_value(
37///   r#"{ "test": 5 } // test"#,
38///   &Default::default(),
39/// ).unwrap();
40/// ```
41///
42/// Or to a concrete type:
43///
44/// ```rs
45/// use jsonc_parser::parse_to_serde_value;
46///
47/// #[derive(serde::Deserialize)]
48/// struct Config {
49///   test: u32,
50/// }
51///
52/// let config: Config = parse_to_serde_value(
53///   r#"{ "test": 5 } // test"#,
54///   &Default::default(),
55/// ).unwrap();
56/// ```
57///
58/// Empty or whitespace-only input deserializes as `null`, which means
59/// `Option<T>` will produce `None` while other types will return a
60/// type-mismatch error.
61pub fn parse_to_serde_value<T: ::serde::de::DeserializeOwned>(
62  text: &str,
63  parse_options: &ParseOptions,
64) -> Result<T, ParseError> {
65  let mut parser = JsoncParser::new(text, parse_options);
66
67  let token = parser.scan()?;
68  match token {
69    Some(token) => parser.put_back(token),
70    None => parser.put_back(Token::Null),
71  }
72
73  let value = T::deserialize(&mut parser)?;
74  if parser.scan()?.is_some() {
75    return Err(
76      parser
77        .scanner
78        .create_error_for_current_token(ParseErrorKind::MultipleRootJsonValues),
79    );
80  }
81  Ok(value)
82}
83
84impl ::serde::de::Error for ParseError {
85  fn custom<T: std::fmt::Display>(msg: T) -> Self {
86    ParseError::custom_err(msg.to_string())
87  }
88}
89
90impl<'de> ::serde::Deserializer<'de> for &mut JsoncParser<'de> {
91  type Error = ParseError;
92
93  fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
94    match self.scan()? {
95      None => Err(ParseError::custom_err("unexpected end of input".to_string())),
96      Some(token) => deserialize_token(self, token, visitor),
97    }
98  }
99
100  fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
101    match self.scan()? {
102      Some(Token::Null) => visitor.visit_none(),
103      Some(token) => {
104        self.put_back(token);
105        visitor.visit_some(self)
106      }
107      None => visitor.visit_none(),
108    }
109  }
110
111  fn deserialize_enum<V: Visitor<'de>>(
112    self,
113    _name: &'static str,
114    _variants: &'static [&'static str],
115    visitor: V,
116  ) -> Result<V::Value, Self::Error> {
117    let token = self.scan()?;
118    let token_range = Range::new(self.scanner.token_start(), self.scanner.token_end());
119    let text = self.text;
120    let result = match token {
121      Some(Token::String(s)) => {
122        let variant: String = s.into_owned();
123        visitor.visit_enum(variant.into_deserializer())
124      }
125      Some(Token::OpenBrace) => {
126        // expect exactly one property: { "Variant": data }
127        let key = match self.scan()? {
128          Some(Token::String(s)) => s.into_owned(),
129          _ => {
130            return Err(ParseError::new(
131              token_range,
132              ParseErrorKind::Custom("expected a string key for enum variant".to_string()),
133              text,
134            ));
135          }
136        };
137
138        // expect colon
139        self.scan_object_colon()?;
140
141        let result = visitor.visit_enum(ObjectEnumAccess {
142          parser: self,
143          variant: key,
144        });
145        result.and_then(|v| {
146          // expect close brace
147          match self.scan()? {
148            Some(Token::CloseBrace) => Ok(v),
149            _ => Err(
150              self
151                .scanner
152                .create_error_for_current_token(ParseErrorKind::UnterminatedObject),
153            ),
154          }
155        })
156      }
157      _ => {
158        return Err(ParseError::new(
159          token_range,
160          ParseErrorKind::Custom("expected a string or object for enum".to_string()),
161          text,
162        ));
163      }
164    };
165    result.map_err(|e| e.with_position(token_range, text))
166  }
167
168  fn deserialize_newtype_struct<V: Visitor<'de>>(
169    self,
170    _name: &'static str,
171    visitor: V,
172  ) -> Result<V::Value, Self::Error> {
173    visitor.visit_newtype_struct(self)
174  }
175
176  forward_to_deserialize_any! {
177    bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
178    char str string bytes byte_buf unit unit_struct
179    seq tuple tuple_struct map struct identifier ignored_any
180  }
181}
182
183fn deserialize_token<'de, V: Visitor<'de>>(
184  parser: &mut JsoncParser<'de>,
185  token: Token<'de>,
186  visitor: V,
187) -> Result<V::Value, ParseError> {
188  let token_range = Range::new(parser.scanner.token_start(), parser.scanner.token_end());
189  let text = parser.text;
190  let result = match token {
191    Token::Null => visitor.visit_unit(),
192    Token::Boolean(b) => visitor.visit_bool(b),
193    Token::Number(n) => visit_number(n, visitor),
194    Token::String(s) => match s {
195      Cow::Borrowed(b) => visitor.visit_borrowed_str(b),
196      Cow::Owned(o) => visitor.visit_string(o),
197    },
198    Token::OpenBracket => {
199      parser.enter_container()?;
200      let finished = Cell::new(false);
201      let result = visitor.visit_seq(ScannerSeqAccess {
202        parser,
203        first: true,
204        finished: &finished,
205      });
206      if result.is_ok() && !finished.get() {
207        if let Err(e) = drain_array(parser) {
208          parser.exit_container();
209          return Err(e);
210        }
211      }
212      parser.exit_container();
213      result
214    }
215    Token::OpenBrace => {
216      parser.enter_container()?;
217      let result = visitor.visit_map(ScannerMapAccess { parser, first: true });
218      parser.exit_container();
219      result
220    }
221    other => return Err(parser.unexpected_token_error(&other)),
222  };
223  result.map_err(|e| e.with_position(token_range, text))
224}
225
226// number handling
227
228fn visit_number<'de, V: Visitor<'de>>(raw: &str, visitor: V) -> Result<V::Value, ParseError> {
229  // handle hexadecimal
230  let trimmed = raw.trim_start_matches(['-', '+']);
231  if trimmed.len() > 2 && (trimmed.starts_with("0x") || trimmed.starts_with("0X")) {
232    let hex_part = &trimmed[2..];
233    match i64::from_str_radix(hex_part, 16) {
234      Ok(val) => {
235        let val = if raw.starts_with('-') { -val } else { val };
236        return visitor.visit_i64(val);
237      }
238      Err(_) => return visitor.visit_str(raw),
239    }
240  }
241
242  // strip unary plus
243  let num_str = raw.trim_start_matches('+');
244
245  if let Ok(v) = num_str.parse::<i64>() {
246    return visitor.visit_i64(v);
247  }
248  if let Ok(v) = num_str.parse::<u64>() {
249    return visitor.visit_u64(v);
250  }
251  if let Ok(v) = num_str.parse::<f64>() {
252    return visitor.visit_f64(v);
253  }
254
255  // fallback for unparseable numbers
256  visitor.visit_str(raw)
257}
258
259// array handling
260
261/// Consumes remaining array elements and the closing `]` when a visitor
262/// (e.g. for a tuple) stops reading before the end of the array.
263fn drain_array(parser: &mut JsoncParser) -> Result<(), ParseError> {
264  loop {
265    match parser.scan_array_comma()? {
266      Some(Token::CloseBracket) => return Ok(()),
267      Some(token) => {
268        parser.put_back(token);
269        <::serde::de::IgnoredAny as ::serde::Deserialize>::deserialize(&mut *parser)?;
270      }
271      None => {
272        return Err(
273          parser
274            .scanner
275            .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
276        );
277      }
278    }
279  }
280}
281
282struct ScannerSeqAccess<'a, 'b> {
283  parser: &'b mut JsoncParser<'a>,
284  first: bool,
285  finished: &'b Cell<bool>,
286}
287
288impl<'de, 'b> SeqAccess<'de> for ScannerSeqAccess<'de, 'b> {
289  type Error = ParseError;
290
291  fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> {
292    let token = if self.first {
293      self.first = false;
294      self.parser.scan()?
295    } else {
296      self.parser.scan_array_comma()?
297    };
298
299    match token {
300      Some(Token::CloseBracket) => {
301        self.finished.set(true);
302        Ok(None)
303      }
304      Some(token) => {
305        self.parser.put_back(token);
306        seed.deserialize(&mut *self.parser).map(Some)
307      }
308      None => Err(
309        self
310          .parser
311          .scanner
312          .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
313      ),
314    }
315  }
316}
317
318// object handling
319
320struct ScannerMapAccess<'a, 'b> {
321  parser: &'b mut JsoncParser<'a>,
322  first: bool,
323}
324
325impl<'de, 'b> MapAccess<'de> for ScannerMapAccess<'de, 'b> {
326  type Error = ParseError;
327
328  fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> {
329    let key = self.parser.scan_object_entry(self.first)?;
330    self.first = false;
331
332    match key {
333      None => Ok(None),
334      Some(key) => {
335        let key_str = key.into_string();
336        seed
337          .deserialize(<String as IntoDeserializer<Self::Error>>::into_deserializer(key_str))
338          .map(Some)
339      }
340    }
341  }
342
343  fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, Self::Error> {
344    self.parser.scan_object_colon()?;
345    seed.deserialize(&mut *self.parser)
346  }
347}
348
349// enum handling
350
351struct ObjectEnumAccess<'a, 'b> {
352  parser: &'b mut JsoncParser<'a>,
353  variant: String,
354}
355
356impl<'de, 'b> EnumAccess<'de> for ObjectEnumAccess<'de, 'b> {
357  type Error = ParseError;
358  type Variant = ObjectVariantAccess<'de, 'b>;
359
360  fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> {
361    let variant = seed.deserialize(<String as IntoDeserializer<Self::Error>>::into_deserializer(
362      self.variant,
363    ))?;
364    Ok((variant, ObjectVariantAccess { parser: self.parser }))
365  }
366}
367
368struct ObjectVariantAccess<'a, 'b> {
369  parser: &'b mut JsoncParser<'a>,
370}
371
372impl<'de, 'b> VariantAccess<'de> for ObjectVariantAccess<'de, 'b> {
373  type Error = ParseError;
374
375  fn unit_variant(self) -> Result<(), Self::Error> {
376    ::serde::Deserialize::deserialize(&mut *self.parser)
377  }
378
379  fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value, Self::Error> {
380    seed.deserialize(&mut *self.parser)
381  }
382
383  fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> {
384    match self.parser.scan()? {
385      Some(Token::OpenBracket) => {
386        self.parser.enter_container()?;
387        let finished = Cell::new(false);
388        let result = visitor.visit_seq(ScannerSeqAccess {
389          parser: self.parser,
390          first: true,
391          finished: &finished,
392        });
393        if result.is_ok() && !finished.get() {
394          if let Err(e) = drain_array(self.parser) {
395            self.parser.exit_container();
396            return Err(e);
397          }
398        }
399        self.parser.exit_container();
400        result
401      }
402      _ => Err(ParseError::custom_err(
403        "expected an array for tuple variant".to_string(),
404      )),
405    }
406  }
407
408  fn struct_variant<V: Visitor<'de>>(
409    self,
410    _fields: &'static [&'static str],
411    visitor: V,
412  ) -> Result<V::Value, Self::Error> {
413    match self.parser.scan()? {
414      Some(Token::OpenBrace) => {
415        self.parser.enter_container()?;
416        let result = visitor.visit_map(ScannerMapAccess {
417          parser: self.parser,
418          first: true,
419        });
420        self.parser.exit_container();
421        result
422      }
423      _ => Err(ParseError::custom_err(
424        "expected an object for struct variant".to_string(),
425      )),
426    }
427  }
428}
429
430#[cfg(test)]
431mod tests {
432  use pretty_assertions::assert_eq;
433  use serde_json::Value as SerdeValue;
434  use std::str::FromStr;
435
436  use super::*;
437
438  #[test]
439  fn it_should_error_when_has_error() {
440    assert_has_error(
441      "[][]",
442      "Text cannot contain more than one JSON value on line 1 column 3",
443    );
444  }
445
446  fn assert_has_error(text: &str, message: &str) {
447    let result = parse_to_serde_value::<SerdeValue>(text, &Default::default());
448    match result {
449      Ok(_) => panic!("Expected error, but did not find one."),
450      Err(err) => assert_eq!(err.to_string(), message),
451    }
452  }
453
454  #[test]
455  fn it_should_parse_to_serde_value() {
456    let result = parse_to_serde_value::<SerdeValue>(
457      r#"{ "a": { "a1": 5 }, "b": [0.3e+025], "c": "c1", "d": true, "e": false, "f": null }"#,
458      &Default::default(),
459    )
460    .unwrap();
461
462    let mut expected_value = serde_json::map::Map::new();
463    expected_value.insert("a".to_string(), {
464      let mut inner_obj = serde_json::map::Map::new();
465      inner_obj.insert(
466        "a1".to_string(),
467        SerdeValue::Number(serde_json::Number::from_str("5").unwrap()),
468      );
469      SerdeValue::Object(inner_obj)
470    });
471    expected_value.insert("b".to_string(), {
472      let mut inner_array = Vec::new();
473      inner_array.push(SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap()));
474      SerdeValue::Array(inner_array)
475    });
476    expected_value.insert("c".to_string(), SerdeValue::String("c1".to_string()));
477    expected_value.insert("d".to_string(), SerdeValue::Bool(true));
478    expected_value.insert("e".to_string(), SerdeValue::Bool(false));
479    expected_value.insert("f".to_string(), SerdeValue::Null);
480
481    assert_eq!(result, SerdeValue::Object(expected_value));
482  }
483
484  #[test]
485  fn it_should_parse_hexadecimal_numbers_to_decimal() {
486    let result = parse_to_serde_value::<SerdeValue>(
487      r#"{
488        "hex1": 0x7DF,
489        "hex2": 0xFF,
490        "hex3": 0x10
491      }"#,
492      &Default::default(),
493    )
494    .unwrap();
495
496    let mut expected_value = serde_json::map::Map::new();
497    expected_value.insert("hex1".to_string(), SerdeValue::Number(serde_json::Number::from(2015)));
498    expected_value.insert("hex2".to_string(), SerdeValue::Number(serde_json::Number::from(255)));
499    expected_value.insert("hex3".to_string(), SerdeValue::Number(serde_json::Number::from(16)));
500
501    assert_eq!(result, SerdeValue::Object(expected_value));
502  }
503
504  #[test]
505  fn it_should_parse_unary_plus_numbers() {
506    let result = parse_to_serde_value::<SerdeValue>(
507      r#"{
508        "pos1": +42,
509        "pos2": +0.5,
510        "pos3": +1e10
511      }"#,
512      &Default::default(),
513    )
514    .unwrap();
515
516    let mut expected_value = serde_json::map::Map::new();
517    expected_value.insert("pos1".to_string(), SerdeValue::Number(serde_json::Number::from(42)));
518    expected_value.insert(
519      "pos2".to_string(),
520      SerdeValue::Number(serde_json::Number::from_str("0.5").unwrap()),
521    );
522    expected_value.insert(
523      "pos3".to_string(),
524      SerdeValue::Number(serde_json::Number::from_str("1e10").unwrap()),
525    );
526
527    assert_eq!(result, SerdeValue::Object(expected_value));
528  }
529
530  #[test]
531  fn it_should_deserialize_to_struct() {
532    #[derive(::serde::Deserialize, Debug, PartialEq)]
533    #[serde(crate = "::serde")]
534    struct Config {
535      name: String,
536      value: u32,
537      enabled: bool,
538    }
539
540    let result: Config = parse_to_serde_value(
541      r#"{ "name": "test", "value": 42, "enabled": true }"#,
542      &Default::default(),
543    )
544    .unwrap();
545
546    assert_eq!(
547      result,
548      Config {
549        name: "test".to_string(),
550        value: 42,
551        enabled: true,
552      }
553    );
554  }
555
556  #[test]
557  fn it_should_report_position_on_type_error() {
558    #[derive(::serde::Deserialize, Debug)]
559    #[serde(crate = "::serde")]
560    #[allow(dead_code)]
561    struct Config {
562      name: String,
563    }
564
565    let text = r#"{
566  "name": true
567}"#;
568    let err = parse_to_serde_value::<Config>(text, &Default::default()).unwrap_err();
569    // the error should point at `true` (line 2, column 11)
570    assert_eq!(err.line_display(), 2);
571    assert_eq!(err.column_display(), 11);
572    assert!(err.to_string().contains("invalid type"), "got: {}", err);
573  }
574
575  #[test]
576  fn it_should_deserialize_option_fields() {
577    #[derive(::serde::Deserialize, Debug, PartialEq)]
578    #[serde(crate = "::serde")]
579    struct Config {
580      a: Option<u32>,
581      b: Option<u32>,
582    }
583
584    let result: Config = parse_to_serde_value(r#"{ "a": 5, "b": null }"#, &Default::default()).unwrap();
585
586    assert_eq!(result, Config { a: Some(5), b: None });
587  }
588
589  #[test]
590  fn it_should_deserialize_enum() {
591    #[derive(::serde::Deserialize, Debug, PartialEq)]
592    #[serde(crate = "::serde")]
593    enum Color {
594      Red,
595      Green,
596      Blue,
597    }
598
599    #[derive(::serde::Deserialize, Debug, PartialEq)]
600    #[serde(crate = "::serde")]
601    struct Config {
602      color: Color,
603    }
604
605    let result: Config = parse_to_serde_value(r#"{ "color": "Red" }"#, &Default::default()).unwrap();
606
607    assert_eq!(result, Config { color: Color::Red });
608  }
609
610  #[test]
611  fn it_should_deserialize_complex_enum() {
612    #[derive(::serde::Deserialize, Debug, PartialEq)]
613    #[serde(crate = "::serde")]
614    enum Shape {
615      Circle(f64),
616      Rectangle { width: f64, height: f64 },
617    }
618
619    let result: Shape = parse_to_serde_value(r#"{ "Circle": 5.0 }"#, &Default::default()).unwrap();
620    assert_eq!(result, Shape::Circle(5.0));
621
622    let result: Shape = parse_to_serde_value(
623      r#"{ "Rectangle": { "width": 3.0, "height": 4.0 } }"#,
624      &Default::default(),
625    )
626    .unwrap();
627    assert_eq!(
628      result,
629      Shape::Rectangle {
630        width: 3.0,
631        height: 4.0
632      }
633    );
634  }
635
636  #[test]
637  fn it_should_return_null_for_empty_input() {
638    let result = parse_to_serde_value::<SerdeValue>("", &Default::default()).unwrap();
639    assert_eq!(result, SerdeValue::Null);
640  }
641
642  #[test]
643  fn it_should_return_none_for_empty_input_with_option() {
644    let result: Option<SerdeValue> = parse_to_serde_value("", &Default::default()).unwrap();
645    assert_eq!(result, None);
646  }
647
648  #[test]
649  fn it_should_return_some_for_non_empty_input_with_option() {
650    let result: Option<SerdeValue> = parse_to_serde_value(r#"{ "a": 1 }"#, &Default::default()).unwrap();
651    assert!(result.is_some());
652  }
653
654  #[test]
655  fn it_should_return_none_for_empty_input_with_option_struct() {
656    #[derive(::serde::Deserialize, Debug, PartialEq)]
657    #[serde(crate = "::serde")]
658    struct Config {
659      value: u32,
660    }
661
662    let result: Option<Config> = parse_to_serde_value("", &Default::default()).unwrap();
663    assert_eq!(result, None);
664
665    let result: Option<Config> = parse_to_serde_value("  \n  ", &Default::default()).unwrap();
666    assert_eq!(result, None);
667  }
668
669  #[test]
670  fn it_should_deserialize_tuples() {
671    // 1-element
672    let result: (u8,) = parse_to_serde_value("[1]", &Default::default()).unwrap();
673    assert_eq!(result, (1,));
674
675    // 2-element with mixed types
676    let result: (u8, String) = parse_to_serde_value(r#"[1, "hello"]"#, &Default::default()).unwrap();
677    assert_eq!(result, (1, "hello".to_string()));
678
679    // 3-element in an object
680    #[derive(::serde::Deserialize, Debug, PartialEq)]
681    #[serde(crate = "::serde")]
682    struct Config {
683      version: (u8, u8, u8),
684    }
685    let result: Config = parse_to_serde_value(r#"{ "version": [0, 3, 0] }"#, &Default::default()).unwrap();
686    assert_eq!(result, Config { version: (0, 3, 0) });
687
688    // 6-element
689    let result: (u8, u8, u8, u8, u8, u8) = parse_to_serde_value("[1, 2, 3, 4, 5, 6]", &Default::default()).unwrap();
690    assert_eq!(result, (1, 2, 3, 4, 5, 6));
691
692    // 9-element
693    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8) =
694      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9]", &Default::default()).unwrap();
695    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9));
696
697    // 12-element
698    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) =
699      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]", &Default::default()).unwrap();
700    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
701  }
702
703  #[test]
704  fn it_should_handle_comments_in_jsonc() {
705    #[derive(::serde::Deserialize, Debug, PartialEq)]
706    #[serde(crate = "::serde")]
707    struct Config {
708      value: u32,
709    }
710
711    let result: Config = parse_to_serde_value(
712      r#"{
713        // this is a comment
714        "value": 42 /* inline comment */
715      }"#,
716      &Default::default(),
717    )
718    .unwrap();
719
720    assert_eq!(result, Config { value: 42 });
721  }
722}