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