Skip to main content

jsonc_parser/
serde.rs

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