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    let negative = raw.starts_with('-');
234    if let Ok(val) = i64::from_str_radix(hex_part, 16) {
235      return visitor.visit_i64(if negative { -val } else { val });
236    }
237    // fall back to an i128 for the values that don't fit in an i64, which
238    // are the ones that fit in a u64 and `i64::MIN`
239    return match i128::from_str_radix(hex_part, 16) {
240      Ok(val) => {
241        let val = if negative { -val } else { val };
242        if let Ok(val) = i64::try_from(val) {
243          visitor.visit_i64(val)
244        } else if let Ok(val) = u64::try_from(val) {
245          visitor.visit_u64(val)
246        } else {
247          Err(number_out_of_range_error())
248        }
249      }
250      Err(_) => Err(number_out_of_range_error()),
251    };
252  }
253
254  // strip unary plus
255  let num_str = raw.trim_start_matches('+');
256
257  if let Ok(v) = num_str.parse::<i64>() {
258    return visitor.visit_i64(v);
259  }
260  if let Ok(v) = num_str.parse::<u64>() {
261    return visitor.visit_u64(v);
262  }
263  match num_str.parse::<f64>() {
264    Ok(v) if v.is_finite() => visitor.visit_f64(v),
265    // `parse` resolves to infinity instead of erroring for numbers that are
266    // too large and the scanner only ever provides numbers an f64 can parse
267    _ => Err(number_out_of_range_error()),
268  }
269}
270
271/// Errors instead of silently changing the value's JSON type, which is what
272/// visiting a non-finite float would do (ex. `serde_json::Value` turns those
273/// into `null`).
274fn number_out_of_range_error() -> ParseError {
275  ParseError::custom_err("Number is out of range".to_string())
276}
277
278// array handling
279
280/// Consumes remaining array elements and the closing `]` when a visitor
281/// (e.g. for a tuple) stops reading before the end of the array.
282fn drain_array(parser: &mut JsoncParser) -> Result<(), ParseError> {
283  loop {
284    match parser.scan_array_comma()? {
285      Some(Token::CloseBracket) => return Ok(()),
286      Some(token) => {
287        parser.put_back(token);
288        <::serde::de::IgnoredAny as ::serde::Deserialize>::deserialize(&mut *parser)?;
289      }
290      None => {
291        return Err(
292          parser
293            .scanner
294            .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
295        );
296      }
297    }
298  }
299}
300
301struct ScannerSeqAccess<'a, 'b> {
302  parser: &'b mut JsoncParser<'a>,
303  first: bool,
304  finished: &'b Cell<bool>,
305}
306
307impl<'de, 'b> SeqAccess<'de> for ScannerSeqAccess<'de, 'b> {
308  type Error = ParseError;
309
310  fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> {
311    let token = if self.first {
312      self.first = false;
313      self.parser.scan()?
314    } else {
315      self.parser.scan_array_comma()?
316    };
317
318    match token {
319      Some(Token::CloseBracket) => {
320        self.finished.set(true);
321        Ok(None)
322      }
323      Some(token) => {
324        self.parser.put_back(token);
325        seed.deserialize(&mut *self.parser).map(Some)
326      }
327      None => Err(
328        self
329          .parser
330          .scanner
331          .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
332      ),
333    }
334  }
335}
336
337// object handling
338
339struct ScannerMapAccess<'a, 'b> {
340  parser: &'b mut JsoncParser<'a>,
341  first: bool,
342}
343
344impl<'de, 'b> MapAccess<'de> for ScannerMapAccess<'de, 'b> {
345  type Error = ParseError;
346
347  fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> {
348    let key = self.parser.scan_object_entry(self.first)?;
349    self.first = false;
350
351    match key {
352      None => Ok(None),
353      Some(key) => {
354        // borrow the key from the source when it's clean, only allocating for
355        // owned (escaped) keys — mirrors the value path's `Cow` keys
356        seed
357          .deserialize(<Cow<'de, str> as IntoDeserializer<Self::Error>>::into_deserializer(
358            key.into_cow(),
359          ))
360          .map(Some)
361      }
362    }
363  }
364
365  fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, Self::Error> {
366    self.parser.scan_object_colon()?;
367    seed.deserialize(&mut *self.parser)
368  }
369}
370
371// enum handling
372
373struct ObjectEnumAccess<'a, 'b> {
374  parser: &'b mut JsoncParser<'a>,
375  variant: String,
376}
377
378impl<'de, 'b> EnumAccess<'de> for ObjectEnumAccess<'de, 'b> {
379  type Error = ParseError;
380  type Variant = ObjectVariantAccess<'de, 'b>;
381
382  fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> {
383    let variant = seed.deserialize(<String as IntoDeserializer<Self::Error>>::into_deserializer(
384      self.variant,
385    ))?;
386    Ok((variant, ObjectVariantAccess { parser: self.parser }))
387  }
388}
389
390struct ObjectVariantAccess<'a, 'b> {
391  parser: &'b mut JsoncParser<'a>,
392}
393
394impl<'de, 'b> VariantAccess<'de> for ObjectVariantAccess<'de, 'b> {
395  type Error = ParseError;
396
397  fn unit_variant(self) -> Result<(), Self::Error> {
398    ::serde::Deserialize::deserialize(&mut *self.parser)
399  }
400
401  fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value, Self::Error> {
402    seed.deserialize(&mut *self.parser)
403  }
404
405  fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> {
406    match self.parser.scan()? {
407      Some(Token::OpenBracket) => {
408        self.parser.enter_container()?;
409        let finished = Cell::new(false);
410        let result = visitor.visit_seq(ScannerSeqAccess {
411          parser: self.parser,
412          first: true,
413          finished: &finished,
414        });
415        if result.is_ok() && !finished.get() {
416          if let Err(e) = drain_array(self.parser) {
417            self.parser.exit_container();
418            return Err(e);
419          }
420        }
421        self.parser.exit_container();
422        result
423      }
424      _ => Err(ParseError::custom_err(
425        "expected an array for tuple variant".to_string(),
426      )),
427    }
428  }
429
430  fn struct_variant<V: Visitor<'de>>(
431    self,
432    _fields: &'static [&'static str],
433    visitor: V,
434  ) -> Result<V::Value, Self::Error> {
435    match self.parser.scan()? {
436      Some(Token::OpenBrace) => {
437        self.parser.enter_container()?;
438        let result = visitor.visit_map(ScannerMapAccess {
439          parser: self.parser,
440          first: true,
441        });
442        self.parser.exit_container();
443        result
444      }
445      _ => Err(ParseError::custom_err(
446        "expected an object for struct variant".to_string(),
447      )),
448    }
449  }
450}
451
452#[cfg(test)]
453mod tests {
454  use pretty_assertions::assert_eq;
455  use serde_json::Value as SerdeValue;
456  use std::str::FromStr;
457
458  use super::*;
459
460  #[test]
461  fn it_should_error_when_has_error() {
462    assert_has_error(
463      "[][]",
464      "Text cannot contain more than one JSON value on line 1 column 3",
465    );
466  }
467
468  fn assert_has_error(text: &str, message: &str) {
469    let result = parse_to_serde_value::<SerdeValue>(text, &Default::default());
470    match result {
471      Ok(_) => panic!("Expected error, but did not find one."),
472      Err(err) => assert_eq!(err.to_string(), message),
473    }
474  }
475
476  #[test]
477  fn it_should_parse_to_serde_value() {
478    let result = parse_to_serde_value::<SerdeValue>(
479      r#"{ "a": { "a1": 5 }, "b": [0.3e+025], "c": "c1", "d": true, "e": false, "f": null }"#,
480      &Default::default(),
481    )
482    .unwrap();
483
484    let mut expected_value = serde_json::map::Map::new();
485    expected_value.insert("a".to_string(), {
486      let mut inner_obj = serde_json::map::Map::new();
487      inner_obj.insert(
488        "a1".to_string(),
489        SerdeValue::Number(serde_json::Number::from_str("5").unwrap()),
490      );
491      SerdeValue::Object(inner_obj)
492    });
493    expected_value.insert("b".to_string(), {
494      let mut inner_array = Vec::new();
495      inner_array.push(SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap()));
496      SerdeValue::Array(inner_array)
497    });
498    expected_value.insert("c".to_string(), SerdeValue::String("c1".to_string()));
499    expected_value.insert("d".to_string(), SerdeValue::Bool(true));
500    expected_value.insert("e".to_string(), SerdeValue::Bool(false));
501    expected_value.insert("f".to_string(), SerdeValue::Null);
502
503    assert_eq!(result, SerdeValue::Object(expected_value));
504  }
505
506  #[test]
507  fn it_should_parse_hexadecimal_numbers_to_decimal() {
508    let result = parse_to_serde_value::<SerdeValue>(
509      r#"{
510        "hex1": 0x7DF,
511        "hex2": 0xFF,
512        "hex3": 0x10
513      }"#,
514      &Default::default(),
515    )
516    .unwrap();
517
518    let mut expected_value = serde_json::map::Map::new();
519    expected_value.insert("hex1".to_string(), SerdeValue::Number(serde_json::Number::from(2015)));
520    expected_value.insert("hex2".to_string(), SerdeValue::Number(serde_json::Number::from(255)));
521    expected_value.insert("hex3".to_string(), SerdeValue::Number(serde_json::Number::from(16)));
522
523    assert_eq!(result, SerdeValue::Object(expected_value));
524  }
525
526  #[test]
527  fn it_should_parse_keywords_as_loose_property_names() {
528    let result = parse_to_serde_value::<SerdeValue>(r#"{ true: 1, false: 2 null: 3 }"#, &Default::default()).unwrap();
529    assert_eq!(result, serde_json::json!({ "true": 1, "false": 2, "null": 3 }));
530    assert_has_strict_error(
531      r#"{ null: 1 }"#,
532      "Expected string for object property on line 1 column 3",
533    );
534    assert_has_strict_error(r#"{ "a": 1 true: 2 }"#, "Expected comma on line 1 column 9");
535  }
536
537  #[test]
538  fn it_should_parse_unary_plus_numbers() {
539    let result = parse_to_serde_value::<SerdeValue>(
540      r#"{
541        "pos1": +42,
542        "pos2": +0.5,
543        "pos3": +1e10
544      }"#,
545      &Default::default(),
546    )
547    .unwrap();
548
549    let mut expected_value = serde_json::map::Map::new();
550    expected_value.insert("pos1".to_string(), SerdeValue::Number(serde_json::Number::from(42)));
551    expected_value.insert(
552      "pos2".to_string(),
553      SerdeValue::Number(serde_json::Number::from_str("0.5").unwrap()),
554    );
555    expected_value.insert(
556      "pos3".to_string(),
557      SerdeValue::Number(serde_json::Number::from_str("1e10").unwrap()),
558    );
559
560    assert_eq!(result, SerdeValue::Object(expected_value));
561  }
562
563  #[test]
564  fn it_should_parse_bare_decimal_point_numbers() {
565    let result = parse_to_serde_value::<SerdeValue>(r#"[.5, -.5, 5., 5.e3]"#, &Default::default()).unwrap();
566    assert_eq!(result, serde_json::json!([0.5, -0.5, 5.0, 5000.0]));
567    assert!(result[2].is_f64());
568  }
569
570  #[test]
571  fn it_should_error_for_non_finite_numbers() {
572    // serde_json has no representation for these
573    assert_has_error(r#"{ "a": Infinity }"#, "Number is out of range on line 1 column 8");
574    assert_has_error("[-Infinity]", "Number is out of range on line 1 column 2");
575    assert_has_error("NaN", "Number is out of range on line 1 column 1");
576    let value = parse_to_serde_value::<f64>("-Infinity", &Default::default());
577    assert!(value.is_err());
578  }
579
580  #[test]
581  fn it_should_error_when_number_is_out_of_f64_range() {
582    assert_has_error(r#"{ "amount": 1e400 }"#, "Number is out of range on line 1 column 13");
583    assert_has_error("[-1e400]", "Number is out of range on line 1 column 2");
584    assert_has_error("1.7976931348623159e308", "Number is out of range on line 1 column 1");
585
586    // deserializing to a float should error as well instead of resolving to infinity
587    let err = parse_to_serde_value::<f64>("1e400", &Default::default()).unwrap_err();
588    assert_eq!(err.to_string(), "Number is out of range on line 1 column 1");
589
590    // the number being out of range still errors when the value is ignored
591    #[derive(::serde::Deserialize, Debug, PartialEq)]
592    #[serde(crate = "::serde")]
593    struct Amount {
594      amount: u32,
595    }
596    let err = parse_to_serde_value::<Amount>(r#"{ "amount": 1, "other": 1e400 }"#, &Default::default()).unwrap_err();
597    assert_eq!(err.to_string(), "Number is out of range on line 1 column 25");
598
599    // numbers that underflow are fine
600    let result = parse_to_serde_value::<f64>("1e-400", &Default::default()).unwrap();
601    assert_eq!(result, 0.0);
602    let result = parse_to_serde_value::<f64>("-1e-400", &Default::default()).unwrap();
603    assert_eq!(result, -0.0);
604    assert!(result.is_sign_negative());
605
606    // the largest finite f64 is fine
607    let result = parse_to_serde_value::<f64>("1.7976931348623157e308", &Default::default()).unwrap();
608    assert_eq!(result, f64::MAX);
609  }
610
611  #[test]
612  fn it_should_error_when_hexadecimal_number_is_out_of_range() {
613    assert_has_error(
614      r#"{ "value": 0xFFFFFFFFFFFFFFFFFF }"#,
615      "Number is out of range on line 1 column 12",
616    );
617    assert_has_error("-0x8000000000000001", "Number is out of range on line 1 column 1");
618
619    // hexadecimal numbers that don't fit in an i64, but fit in a u64
620    let result = parse_to_serde_value::<u64>("0x8000000000000000", &Default::default()).unwrap();
621    assert_eq!(result, 9223372036854775808);
622
623    // i64::MIN
624    let result = parse_to_serde_value::<i64>("-0x8000000000000000", &Default::default()).unwrap();
625    assert_eq!(result, i64::MIN);
626  }
627
628  #[test]
629  fn it_should_deserialize_to_struct() {
630    #[derive(::serde::Deserialize, Debug, PartialEq)]
631    #[serde(crate = "::serde")]
632    struct Config {
633      name: String,
634      value: u32,
635      enabled: bool,
636    }
637
638    let result: Config = parse_to_serde_value(
639      r#"{ "name": "test", "value": 42, "enabled": true }"#,
640      &Default::default(),
641    )
642    .unwrap();
643
644    assert_eq!(
645      result,
646      Config {
647        name: "test".to_string(),
648        value: 42,
649        enabled: true,
650      }
651    );
652  }
653
654  #[test]
655  fn it_should_report_position_on_type_error() {
656    #[derive(::serde::Deserialize, Debug)]
657    #[serde(crate = "::serde")]
658    #[allow(dead_code)]
659    struct Config {
660      name: String,
661    }
662
663    let text = r#"{
664  "name": true
665}"#;
666    let err = parse_to_serde_value::<Config>(text, &Default::default()).unwrap_err();
667    // the error should point at `true` (line 2, column 11)
668    assert_eq!(err.line_display(), 2);
669    assert_eq!(err.column_display(), 11);
670    assert!(err.to_string().contains("invalid type"), "got: {}", err);
671  }
672
673  #[test]
674  fn it_should_deserialize_option_fields() {
675    #[derive(::serde::Deserialize, Debug, PartialEq)]
676    #[serde(crate = "::serde")]
677    struct Config {
678      a: Option<u32>,
679      b: Option<u32>,
680    }
681
682    let result: Config = parse_to_serde_value(r#"{ "a": 5, "b": null }"#, &Default::default()).unwrap();
683
684    assert_eq!(result, Config { a: Some(5), b: None });
685  }
686
687  #[test]
688  fn it_should_deserialize_enum() {
689    #[derive(::serde::Deserialize, Debug, PartialEq)]
690    #[serde(crate = "::serde")]
691    enum Color {
692      Red,
693      Green,
694      Blue,
695    }
696
697    #[derive(::serde::Deserialize, Debug, PartialEq)]
698    #[serde(crate = "::serde")]
699    struct Config {
700      color: Color,
701    }
702
703    let result: Config = parse_to_serde_value(r#"{ "color": "Red" }"#, &Default::default()).unwrap();
704
705    assert_eq!(result, Config { color: Color::Red });
706  }
707
708  #[test]
709  fn it_should_deserialize_complex_enum() {
710    #[derive(::serde::Deserialize, Debug, PartialEq)]
711    #[serde(crate = "::serde")]
712    enum Shape {
713      Circle(f64),
714      Rectangle { width: f64, height: f64 },
715    }
716
717    let result: Shape = parse_to_serde_value(r#"{ "Circle": 5.0 }"#, &Default::default()).unwrap();
718    assert_eq!(result, Shape::Circle(5.0));
719
720    let result: Shape = parse_to_serde_value(
721      r#"{ "Rectangle": { "width": 3.0, "height": 4.0 } }"#,
722      &Default::default(),
723    )
724    .unwrap();
725    assert_eq!(
726      result,
727      Shape::Rectangle {
728        width: 3.0,
729        height: 4.0
730      }
731    );
732  }
733
734  #[test]
735  fn it_should_return_null_for_empty_input() {
736    let result = parse_to_serde_value::<SerdeValue>("", &Default::default()).unwrap();
737    assert_eq!(result, SerdeValue::Null);
738  }
739
740  #[test]
741  fn it_should_return_none_for_empty_input_with_option() {
742    let result: Option<SerdeValue> = parse_to_serde_value("", &Default::default()).unwrap();
743    assert_eq!(result, None);
744  }
745
746  #[test]
747  fn it_should_return_some_for_non_empty_input_with_option() {
748    let result: Option<SerdeValue> = parse_to_serde_value(r#"{ "a": 1 }"#, &Default::default()).unwrap();
749    assert!(result.is_some());
750  }
751
752  #[test]
753  fn it_should_return_none_for_empty_input_with_option_struct() {
754    #[derive(::serde::Deserialize, Debug, PartialEq)]
755    #[serde(crate = "::serde")]
756    struct Config {
757      value: u32,
758    }
759
760    let result: Option<Config> = parse_to_serde_value("", &Default::default()).unwrap();
761    assert_eq!(result, None);
762
763    let result: Option<Config> = parse_to_serde_value("  \n  ", &Default::default()).unwrap();
764    assert_eq!(result, None);
765  }
766
767  #[test]
768  fn it_should_deserialize_tuples() {
769    // 1-element
770    let result: (u8,) = parse_to_serde_value("[1]", &Default::default()).unwrap();
771    assert_eq!(result, (1,));
772
773    // 2-element with mixed types
774    let result: (u8, String) = parse_to_serde_value(r#"[1, "hello"]"#, &Default::default()).unwrap();
775    assert_eq!(result, (1, "hello".to_string()));
776
777    // 3-element in an object
778    #[derive(::serde::Deserialize, Debug, PartialEq)]
779    #[serde(crate = "::serde")]
780    struct Config {
781      version: (u8, u8, u8),
782    }
783    let result: Config = parse_to_serde_value(r#"{ "version": [0, 3, 0] }"#, &Default::default()).unwrap();
784    assert_eq!(result, Config { version: (0, 3, 0) });
785
786    // 6-element
787    let result: (u8, u8, u8, u8, u8, u8) = parse_to_serde_value("[1, 2, 3, 4, 5, 6]", &Default::default()).unwrap();
788    assert_eq!(result, (1, 2, 3, 4, 5, 6));
789
790    // 9-element
791    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8) =
792      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9]", &Default::default()).unwrap();
793    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9));
794
795    // 12-element
796    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) =
797      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]", &Default::default()).unwrap();
798    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
799  }
800
801  #[test]
802  fn it_should_handle_comments_in_jsonc() {
803    #[derive(::serde::Deserialize, Debug, PartialEq)]
804    #[serde(crate = "::serde")]
805    struct Config {
806      value: u32,
807    }
808
809    let result: Config = parse_to_serde_value(
810      r#"{
811        // this is a comment
812        "value": 42 /* inline comment */
813      }"#,
814      &Default::default(),
815    )
816    .unwrap();
817
818    assert_eq!(result, Config { value: 42 });
819  }
820
821  #[test]
822  fn missing_comma_between_array_elements() {
823    let result = parse_to_serde_value::<SerdeValue>("[1 2]", &Default::default()).unwrap();
824    assert_eq!(result, serde_json::json!([1, 2]));
825
826    // but is strict when strict
827    assert_has_strict_error("[1 2]", "Expected comma on line 1 column 3");
828    assert_has_strict_error("[01]", "Expected comma on line 1 column 3");
829    assert_has_strict_error(r#"["a" "b"]"#, "Expected comma on line 1 column 5");
830    assert_has_strict_error("[true false]", "Expected comma on line 1 column 6");
831    assert_has_strict_error("[null null]", "Expected comma on line 1 column 6");
832    assert_has_strict_error("[[1] [2]]", "Expected comma on line 1 column 5");
833    assert_has_strict_error(r#"[{"a":1} {"b":2}]"#, "Expected comma on line 1 column 9");
834
835    for text in ["[]", "[1,2]", "[1 , 2]", "[[1],[2]]", r#"[{"a":1},{"b":2}]"#] {
836      parse_to_serde_value_strict::<SerdeValue>(text).unwrap();
837    }
838  }
839
840  #[test]
841  fn missing_comma_between_array_elements_when_draining() {
842    // a tuple stops reading before the end of the array, so the
843    // remaining elements are drained and should still be strict
844    assert_has_strict_drain_error::<(u32,)>("[1 2]", "Expected comma on line 1 column 3");
845    // the drained element here ends with a `}`
846    assert_has_strict_drain_error::<(u32, SerdeValue)>(r#"[1, {"a":2} 3]"#, "Expected comma on line 1 column 12");
847  }
848
849  #[test]
850  fn missing_comma_with_comment_between_array_elements() {
851    // when comments are allowed but missing commas are not,
852    // should still detect the missing comma after the comment is skipped
853    let result = parse_to_serde_value::<SerdeValue>(
854      r#"[
855  1 // comment here
856  2
857]"#,
858      &ParseOptions {
859        allow_comments: true,
860        allow_missing_commas: false,
861        ..Default::default()
862      },
863    );
864    match result {
865      Ok(_) => panic!("Expected error, but did not find one."),
866      Err(err) => assert_eq!(err.to_string(), "Expected comma on line 2 column 4"),
867    }
868  }
869
870  #[track_caller]
871  fn assert_has_strict_error(text: &str, message: &str) {
872    match parse_to_serde_value_strict::<SerdeValue>(text) {
873      Ok(_) => panic!("Expected error, but did not find one."),
874      Err(err) => assert_eq!(err.to_string(), message),
875    }
876  }
877
878  #[track_caller]
879  fn assert_has_strict_drain_error<T: ::serde::de::DeserializeOwned>(text: &str, message: &str) {
880    match parse_to_serde_value_strict::<T>(text) {
881      Ok(_) => panic!("Expected error, but did not find one."),
882      Err(err) => assert_eq!(err.to_string(), message),
883    }
884  }
885
886  fn parse_to_serde_value_strict<T: ::serde::de::DeserializeOwned>(text: &str) -> Result<T, ParseError> {
887    parse_to_serde_value(
888      text,
889      &ParseOptions {
890        allow_comments: false,
891        allow_loose_object_property_names: false,
892        allow_trailing_commas: false,
893        allow_missing_commas: false,
894        allow_single_quoted_strings: false,
895        allow_hexadecimal_numbers: false,
896        allow_unary_plus_numbers: false,
897        allow_bare_decimal_point_numbers: false,
898        allow_non_finite_numbers: false,
899        allow_extended_string_escapes: false,
900      },
901    )
902  }
903}