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        // borrow the key from the source when it's clean, only allocating for
336        // owned (escaped) keys — mirrors the value path's `Cow` keys
337        seed
338          .deserialize(<Cow<'de, str> as IntoDeserializer<Self::Error>>::into_deserializer(
339            key.into_cow(),
340          ))
341          .map(Some)
342      }
343    }
344  }
345
346  fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, Self::Error> {
347    self.parser.scan_object_colon()?;
348    seed.deserialize(&mut *self.parser)
349  }
350}
351
352// enum handling
353
354struct ObjectEnumAccess<'a, 'b> {
355  parser: &'b mut JsoncParser<'a>,
356  variant: String,
357}
358
359impl<'de, 'b> EnumAccess<'de> for ObjectEnumAccess<'de, 'b> {
360  type Error = ParseError;
361  type Variant = ObjectVariantAccess<'de, 'b>;
362
363  fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> {
364    let variant = seed.deserialize(<String as IntoDeserializer<Self::Error>>::into_deserializer(
365      self.variant,
366    ))?;
367    Ok((variant, ObjectVariantAccess { parser: self.parser }))
368  }
369}
370
371struct ObjectVariantAccess<'a, 'b> {
372  parser: &'b mut JsoncParser<'a>,
373}
374
375impl<'de, 'b> VariantAccess<'de> for ObjectVariantAccess<'de, 'b> {
376  type Error = ParseError;
377
378  fn unit_variant(self) -> Result<(), Self::Error> {
379    ::serde::Deserialize::deserialize(&mut *self.parser)
380  }
381
382  fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value, Self::Error> {
383    seed.deserialize(&mut *self.parser)
384  }
385
386  fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> {
387    match self.parser.scan()? {
388      Some(Token::OpenBracket) => {
389        self.parser.enter_container()?;
390        let finished = Cell::new(false);
391        let result = visitor.visit_seq(ScannerSeqAccess {
392          parser: self.parser,
393          first: true,
394          finished: &finished,
395        });
396        if result.is_ok() && !finished.get() {
397          if let Err(e) = drain_array(self.parser) {
398            self.parser.exit_container();
399            return Err(e);
400          }
401        }
402        self.parser.exit_container();
403        result
404      }
405      _ => Err(ParseError::custom_err(
406        "expected an array for tuple variant".to_string(),
407      )),
408    }
409  }
410
411  fn struct_variant<V: Visitor<'de>>(
412    self,
413    _fields: &'static [&'static str],
414    visitor: V,
415  ) -> Result<V::Value, Self::Error> {
416    match self.parser.scan()? {
417      Some(Token::OpenBrace) => {
418        self.parser.enter_container()?;
419        let result = visitor.visit_map(ScannerMapAccess {
420          parser: self.parser,
421          first: true,
422        });
423        self.parser.exit_container();
424        result
425      }
426      _ => Err(ParseError::custom_err(
427        "expected an object for struct variant".to_string(),
428      )),
429    }
430  }
431}
432
433#[cfg(test)]
434mod tests {
435  use pretty_assertions::assert_eq;
436  use serde_json::Value as SerdeValue;
437  use std::str::FromStr;
438
439  use super::*;
440
441  #[test]
442  fn it_should_error_when_has_error() {
443    assert_has_error(
444      "[][]",
445      "Text cannot contain more than one JSON value on line 1 column 3",
446    );
447  }
448
449  fn assert_has_error(text: &str, message: &str) {
450    let result = parse_to_serde_value::<SerdeValue>(text, &Default::default());
451    match result {
452      Ok(_) => panic!("Expected error, but did not find one."),
453      Err(err) => assert_eq!(err.to_string(), message),
454    }
455  }
456
457  #[test]
458  fn it_should_parse_to_serde_value() {
459    let result = parse_to_serde_value::<SerdeValue>(
460      r#"{ "a": { "a1": 5 }, "b": [0.3e+025], "c": "c1", "d": true, "e": false, "f": null }"#,
461      &Default::default(),
462    )
463    .unwrap();
464
465    let mut expected_value = serde_json::map::Map::new();
466    expected_value.insert("a".to_string(), {
467      let mut inner_obj = serde_json::map::Map::new();
468      inner_obj.insert(
469        "a1".to_string(),
470        SerdeValue::Number(serde_json::Number::from_str("5").unwrap()),
471      );
472      SerdeValue::Object(inner_obj)
473    });
474    expected_value.insert("b".to_string(), {
475      let mut inner_array = Vec::new();
476      inner_array.push(SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap()));
477      SerdeValue::Array(inner_array)
478    });
479    expected_value.insert("c".to_string(), SerdeValue::String("c1".to_string()));
480    expected_value.insert("d".to_string(), SerdeValue::Bool(true));
481    expected_value.insert("e".to_string(), SerdeValue::Bool(false));
482    expected_value.insert("f".to_string(), SerdeValue::Null);
483
484    assert_eq!(result, SerdeValue::Object(expected_value));
485  }
486
487  #[test]
488  fn it_should_parse_hexadecimal_numbers_to_decimal() {
489    let result = parse_to_serde_value::<SerdeValue>(
490      r#"{
491        "hex1": 0x7DF,
492        "hex2": 0xFF,
493        "hex3": 0x10
494      }"#,
495      &Default::default(),
496    )
497    .unwrap();
498
499    let mut expected_value = serde_json::map::Map::new();
500    expected_value.insert("hex1".to_string(), SerdeValue::Number(serde_json::Number::from(2015)));
501    expected_value.insert("hex2".to_string(), SerdeValue::Number(serde_json::Number::from(255)));
502    expected_value.insert("hex3".to_string(), SerdeValue::Number(serde_json::Number::from(16)));
503
504    assert_eq!(result, SerdeValue::Object(expected_value));
505  }
506
507  #[test]
508  fn it_should_parse_unary_plus_numbers() {
509    let result = parse_to_serde_value::<SerdeValue>(
510      r#"{
511        "pos1": +42,
512        "pos2": +0.5,
513        "pos3": +1e10
514      }"#,
515      &Default::default(),
516    )
517    .unwrap();
518
519    let mut expected_value = serde_json::map::Map::new();
520    expected_value.insert("pos1".to_string(), SerdeValue::Number(serde_json::Number::from(42)));
521    expected_value.insert(
522      "pos2".to_string(),
523      SerdeValue::Number(serde_json::Number::from_str("0.5").unwrap()),
524    );
525    expected_value.insert(
526      "pos3".to_string(),
527      SerdeValue::Number(serde_json::Number::from_str("1e10").unwrap()),
528    );
529
530    assert_eq!(result, SerdeValue::Object(expected_value));
531  }
532
533  #[test]
534  fn it_should_deserialize_to_struct() {
535    #[derive(::serde::Deserialize, Debug, PartialEq)]
536    #[serde(crate = "::serde")]
537    struct Config {
538      name: String,
539      value: u32,
540      enabled: bool,
541    }
542
543    let result: Config = parse_to_serde_value(
544      r#"{ "name": "test", "value": 42, "enabled": true }"#,
545      &Default::default(),
546    )
547    .unwrap();
548
549    assert_eq!(
550      result,
551      Config {
552        name: "test".to_string(),
553        value: 42,
554        enabled: true,
555      }
556    );
557  }
558
559  #[test]
560  fn it_should_report_position_on_type_error() {
561    #[derive(::serde::Deserialize, Debug)]
562    #[serde(crate = "::serde")]
563    #[allow(dead_code)]
564    struct Config {
565      name: String,
566    }
567
568    let text = r#"{
569  "name": true
570}"#;
571    let err = parse_to_serde_value::<Config>(text, &Default::default()).unwrap_err();
572    // the error should point at `true` (line 2, column 11)
573    assert_eq!(err.line_display(), 2);
574    assert_eq!(err.column_display(), 11);
575    assert!(err.to_string().contains("invalid type"), "got: {}", err);
576  }
577
578  #[test]
579  fn it_should_deserialize_option_fields() {
580    #[derive(::serde::Deserialize, Debug, PartialEq)]
581    #[serde(crate = "::serde")]
582    struct Config {
583      a: Option<u32>,
584      b: Option<u32>,
585    }
586
587    let result: Config = parse_to_serde_value(r#"{ "a": 5, "b": null }"#, &Default::default()).unwrap();
588
589    assert_eq!(result, Config { a: Some(5), b: None });
590  }
591
592  #[test]
593  fn it_should_deserialize_enum() {
594    #[derive(::serde::Deserialize, Debug, PartialEq)]
595    #[serde(crate = "::serde")]
596    enum Color {
597      Red,
598      Green,
599      Blue,
600    }
601
602    #[derive(::serde::Deserialize, Debug, PartialEq)]
603    #[serde(crate = "::serde")]
604    struct Config {
605      color: Color,
606    }
607
608    let result: Config = parse_to_serde_value(r#"{ "color": "Red" }"#, &Default::default()).unwrap();
609
610    assert_eq!(result, Config { color: Color::Red });
611  }
612
613  #[test]
614  fn it_should_deserialize_complex_enum() {
615    #[derive(::serde::Deserialize, Debug, PartialEq)]
616    #[serde(crate = "::serde")]
617    enum Shape {
618      Circle(f64),
619      Rectangle { width: f64, height: f64 },
620    }
621
622    let result: Shape = parse_to_serde_value(r#"{ "Circle": 5.0 }"#, &Default::default()).unwrap();
623    assert_eq!(result, Shape::Circle(5.0));
624
625    let result: Shape = parse_to_serde_value(
626      r#"{ "Rectangle": { "width": 3.0, "height": 4.0 } }"#,
627      &Default::default(),
628    )
629    .unwrap();
630    assert_eq!(
631      result,
632      Shape::Rectangle {
633        width: 3.0,
634        height: 4.0
635      }
636    );
637  }
638
639  #[test]
640  fn it_should_return_null_for_empty_input() {
641    let result = parse_to_serde_value::<SerdeValue>("", &Default::default()).unwrap();
642    assert_eq!(result, SerdeValue::Null);
643  }
644
645  #[test]
646  fn it_should_return_none_for_empty_input_with_option() {
647    let result: Option<SerdeValue> = parse_to_serde_value("", &Default::default()).unwrap();
648    assert_eq!(result, None);
649  }
650
651  #[test]
652  fn it_should_return_some_for_non_empty_input_with_option() {
653    let result: Option<SerdeValue> = parse_to_serde_value(r#"{ "a": 1 }"#, &Default::default()).unwrap();
654    assert!(result.is_some());
655  }
656
657  #[test]
658  fn it_should_return_none_for_empty_input_with_option_struct() {
659    #[derive(::serde::Deserialize, Debug, PartialEq)]
660    #[serde(crate = "::serde")]
661    struct Config {
662      value: u32,
663    }
664
665    let result: Option<Config> = parse_to_serde_value("", &Default::default()).unwrap();
666    assert_eq!(result, None);
667
668    let result: Option<Config> = parse_to_serde_value("  \n  ", &Default::default()).unwrap();
669    assert_eq!(result, None);
670  }
671
672  #[test]
673  fn it_should_deserialize_tuples() {
674    // 1-element
675    let result: (u8,) = parse_to_serde_value("[1]", &Default::default()).unwrap();
676    assert_eq!(result, (1,));
677
678    // 2-element with mixed types
679    let result: (u8, String) = parse_to_serde_value(r#"[1, "hello"]"#, &Default::default()).unwrap();
680    assert_eq!(result, (1, "hello".to_string()));
681
682    // 3-element in an object
683    #[derive(::serde::Deserialize, Debug, PartialEq)]
684    #[serde(crate = "::serde")]
685    struct Config {
686      version: (u8, u8, u8),
687    }
688    let result: Config = parse_to_serde_value(r#"{ "version": [0, 3, 0] }"#, &Default::default()).unwrap();
689    assert_eq!(result, Config { version: (0, 3, 0) });
690
691    // 6-element
692    let result: (u8, u8, u8, u8, u8, u8) = parse_to_serde_value("[1, 2, 3, 4, 5, 6]", &Default::default()).unwrap();
693    assert_eq!(result, (1, 2, 3, 4, 5, 6));
694
695    // 9-element
696    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8) =
697      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9]", &Default::default()).unwrap();
698    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9));
699
700    // 12-element
701    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) =
702      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]", &Default::default()).unwrap();
703    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
704  }
705
706  #[test]
707  fn it_should_handle_comments_in_jsonc() {
708    #[derive(::serde::Deserialize, Debug, PartialEq)]
709    #[serde(crate = "::serde")]
710    struct Config {
711      value: u32,
712    }
713
714    let result: Config = parse_to_serde_value(
715      r#"{
716        // this is a comment
717        "value": 42 /* inline comment */
718      }"#,
719      &Default::default(),
720    )
721    .unwrap();
722
723    assert_eq!(result, Config { value: 42 });
724  }
725}