Skip to main content

json/
lib.rs

1/*  Copyright (C) 2025 Saúl Valdelvira
2 *
3 *  This program is free software: you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation, version 3.
6 *
7 *  This program is distributed in the hope that it will be useful,
8 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *  GNU General Public License for more details.
11 *
12 *  You should have received a copy of the GNU General Public License
13 *  along with this program.  If not, see <https://www.gnu.org/licenses/>. */
14
15//! Json parser
16//!
17//! # Example
18//! ```
19//! use json::Json;
20//!
21//! let j = Json::deserialize(r#"{
22//!     "array" : [ 1, 2, "3", null ],
23//!     "true" : true,
24//!     "nested" : {
25//!         "inner" : []
26//!     }
27//! }"#).unwrap();
28//!
29//! let Json::Object(map) = j else { panic!() };
30//! assert!(
31//!     matches!(
32//!         map.get("true"),
33//!         Some(Json::True)));
34//! ```
35
36#![warn(clippy::pedantic)]
37#![allow(clippy::missing_errors_doc, clippy::must_use_candidate)]
38#![cfg_attr(not(feature = "std"), no_std)]
39
40#[macro_use]
41extern crate alloc;
42
43mod prelude {
44    pub use alloc::borrow::Cow;
45    pub use alloc::boxed::Box;
46    pub use alloc::string::{String, ToString};
47    pub use alloc::vec::Vec;
48    pub use core::fmt;
49
50    #[cfg(feature = "std")]
51    pub type Map<K, V> = std::collections::HashMap<K, V>;
52
53    #[cfg(not(feature = "std"))]
54    pub type Map<K, V> = alloc::collections::BTreeMap<K, V>;
55}
56
57use core::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};
58
59use prelude::*;
60
61mod lexer;
62mod parser;
63
64#[cfg(feature = "bindings")]
65pub mod export;
66
67mod error;
68
69type Result<T> = core::result::Result<T, error::Error>;
70
71/// Represents a JSON object
72#[derive(Debug, PartialEq)]
73pub enum Json {
74    Array(Box<[Json]>),
75    Object(Map<Box<str>, Json>),
76    String(Box<str>),
77    Number(f64),
78    True,
79    False,
80    Null,
81}
82
83/// Configures the JSON parser
84#[repr(C)]
85#[derive(Clone, Copy)]
86pub struct JsonConfig {
87    /// Max depth for nested objects
88    pub max_depth: u32,
89
90    /// Allow trailing commas on objects and arrays
91    pub allow_trailing_commas: bool,
92
93    /// Allow comments withing the Json
94    pub allow_comments: bool,
95}
96
97/// Default config used by [`Json::deserialize`]
98const DEFAULT_CONFIG: JsonConfig = JsonConfig {
99    max_depth: u32::MAX,
100    allow_trailing_commas: false,
101    allow_comments: false,
102};
103
104impl Default for JsonConfig {
105    fn default() -> Self {
106        DEFAULT_CONFIG
107    }
108}
109
110impl Json {
111    /// Deserializes the given string into a [Json] object
112    ///
113    /// ## Configuration used
114    /// [`max_depth`](JsonConfig::max_depth) = [`u32::MAX`]
115    ///
116    /// [`recover_from_errors`](JsonConfig::recover_from_errors) = false
117    #[inline]
118    pub fn deserialize(text: impl AsRef<str>) -> Result<Json> {
119        Json::deserialize_with_config(text, DEFAULT_CONFIG)
120    }
121    /// Deserializes the given string into a [Json] object
122    /// using the given [`JsonConfig`]
123    pub fn deserialize_with_config(text: impl AsRef<str>, conf: JsonConfig) -> Result<Json> {
124        let text = text.as_ref();
125        let tokens = lexer::tokenize(text, conf)?;
126        parser::parse(text, &tokens, conf)
127    }
128    /// Serializes the JSON object into a [`fmt::Write`]
129    pub fn serialize(&self, out: &mut dyn fmt::Write) -> fmt::Result {
130        match self {
131            Json::Array(elements) => {
132                out.write_char('[')?;
133                for i in 0..elements.len() {
134                    elements[i].serialize(out)?;
135                    if i < elements.len() - 1 {
136                        out.write_char(',')?;
137                    }
138                }
139                out.write_char(']')?;
140            }
141            Json::Object(obj) => {
142                out.write_char('{')?;
143                let mut first = true;
144                for (k, v) in obj {
145                    if !first {
146                        out.write_char(',')?;
147                    }
148                    first = false;
149                    write!(out, "\"{k}\":")?;
150                    v.serialize(out)?;
151                }
152                out.write_char('}')?;
153            }
154            Json::String(s) => {
155                write!(out, "\"")?;
156                for c in s.chars() {
157                    match c {
158                        '\\' => write!(out, "\\\\"),
159                        '"' => write!(out, "\\\""),
160                        c => write!(out, "{c}"),
161                    }?;
162                }
163                write!(out, "\"")?;
164            }
165            Json::Number(n) => {
166                write!(out, "{n}")?;
167            }
168            Json::True => out.write_str("true")?,
169            Json::False => out.write_str("false")?,
170            Json::Null => out.write_str("null")?,
171        }
172        Ok(())
173    }
174    /// Attempts to get a value of the given json object.
175    /// If the json enum is not an Object variant, or if
176    /// it doesn't contain the key, returns None
177    #[inline]
178    pub fn get(&self, key: impl AsRef<str>) -> Option<&Json> {
179        self.object().and_then(|obj| obj.get(key.as_ref()))
180    }
181    /// Same as [get](Self::get), but with a mutable reference
182    #[inline]
183    pub fn get_mut(&mut self, key: impl AsRef<str>) -> Option<&mut Json> {
184        self.object_mut().and_then(|obj| obj.get_mut(key.as_ref()))
185    }
186    /// Attempts to get a value of the given json array.
187    /// If the json enum is not an Array variant, or if
188    /// it doesn't contain the key, returns None
189    #[inline]
190    pub fn nth(&self, i: usize) -> Option<&Json> {
191        self.array().and_then(|arr| arr.get(i))
192    }
193    /// Same as [nth](Self::nth), but with a mutable reference
194    #[inline]
195    pub fn nth_mut(&mut self, i: usize) -> Option<&mut Json> {
196        self.array_mut().and_then(|arr| arr.get_mut(i))
197    }
198
199    /// Attempts to get the inner [`Number`] of the json
200    /// object, if it is a [`Number`] variant
201    ///
202    /// [`Number`]: Json::Number
203    #[inline]
204    pub const fn number(&self) -> Option<f64> {
205        if let Json::Number(n) = self {
206            Some(*n)
207        } else {
208            None
209        }
210    }
211    /// Expects the json object to be a [`Number`] variant
212    ///
213    /// # Panics
214    /// If the json object is not a [`Number`] variant
215    ///
216    /// [`Number`]: Json::Number
217    #[inline]
218    pub const fn expect_number(&self) -> f64 {
219        self.number().unwrap()
220    }
221    /// Attempts to get a mutable reference to the inner [`Number`]
222    /// of the json object, if it is a [`Number`] variant
223    ///
224    /// [`Number`]: Json::Number
225    #[inline]
226    pub const fn number_mut(&mut self) -> Option<&mut f64> {
227        if let Json::Number(n) = self {
228            Some(n)
229        } else {
230            None
231        }
232    }
233    /// Expects the json object to be a [`Number`] variant
234    /// and gets a mutable reference to the inner number.
235    ///
236    /// # Panics
237    /// If the json object is not a [`Number`] variant
238    ///
239    /// [`Number`]: Json::Number
240    #[inline]
241    pub const fn expect_number_mut(&mut self) -> &mut f64 {
242        self.number_mut().unwrap()
243    }
244
245    /// Attempts to get the inner [`String`] of the json
246    /// object, if it is a [`String`] variant
247    ///
248    /// [`String`]: Json::String
249    #[inline]
250    pub const fn string(&self) -> Option<&str> {
251        if let Json::String(s) = self {
252            Some(s)
253        } else {
254            None
255        }
256    }
257    /// Expects the json object to be a [`String`] variant
258    ///
259    /// # Panics
260    /// If the json object is not a [`String`] variant
261    ///
262    /// [`String`]: Json::String
263    #[inline]
264    pub const fn expect_string(&self) -> &str {
265        self.string().unwrap()
266    }
267    /// Attempts to get a mutable reference to the inner
268    /// [`String`] of the json object, if it is a [`String`] variant
269    ///
270    /// [`String`]: Json::String
271    #[inline]
272    pub const fn string_mut(&mut self) -> Option<&mut str> {
273        if let Json::String(s) = self {
274            Some(s)
275        } else {
276            None
277        }
278    }
279    /// Expects the json object to be a [`String`] variant
280    /// and gets a reference to the inner string
281    ///
282    /// # Panics
283    /// If the json object is not a [`String`] variant
284    ///
285    /// [`String`]: Json::String
286    #[inline]
287    pub const fn expect_string_mut(&mut self) -> &mut str {
288        self.string_mut().unwrap()
289    }
290
291    /// Attempts to get the inner Object of the json object, if
292    /// it is an Object variant
293    #[inline]
294    pub const fn object(&self) -> Option<&Map<Box<str>, Json>> {
295        if let Json::Object(o) = self {
296            Some(o)
297        } else {
298            None
299        }
300    }
301    /// Expects the json object to be a [`Object`] variant
302    /// and gets a reference to the inner object
303    ///
304    /// # Panics
305    /// If the json object is not a [`Object`] variant
306    ///
307    /// [`Object`]: Json::Object
308    #[inline]
309    pub const fn expect_object(&self) -> &Map<Box<str>, Json> {
310        self.object().unwrap()
311    }
312    /// Attempts to get a mutable reference to the inner [`Object`] of
313    /// the json element, if it is an [`Object`] variant
314    ///
315    /// [`Object`]: Json::Object
316    #[inline]
317    pub const fn object_mut(&mut self) -> Option<&mut Map<Box<str>, Json>> {
318        if let Json::Object(o) = self {
319            Some(o)
320        } else {
321            None
322        }
323    }
324    /// Expects the json object to be a [`Object`] variant
325    /// and gets a mutable reference to the inner object
326    ///
327    /// # Panics
328    /// If the json object is not a [`Object`] variant
329    ///
330    /// [`Object`]: Json::Object
331    #[inline]
332    pub const fn expect_object_mut(&mut self) -> &mut Map<Box<str>, Json> {
333        self.object_mut().unwrap()
334    }
335
336    /// Attempts to get the inner Array of the json object, if
337    /// it is an Array variant
338    #[inline]
339    pub const fn array(&self) -> Option<&[Json]> {
340        if let Json::Array(o) = self {
341            Some(o)
342        } else {
343            None
344        }
345    }
346    /// Expects the json object to be a [`Array`] variant
347    ///
348    /// # Panics
349    /// If the json object is not a [`Array`] variant
350    ///
351    /// [`Array`]: Json::Array
352    #[inline]
353    pub const fn expect_array(&self) -> &[Json] {
354        self.array().unwrap()
355    }
356    /// Attempts to get the inner Array of the json object, if
357    /// it is an Array variant
358    #[inline]
359    pub const fn array_mut(&mut self) -> Option<&mut [Json]> {
360        if let Json::Array(o) = self {
361            Some(o)
362        } else {
363            None
364        }
365    }
366    /// Expects the json object to be a [`Array`] variant
367    ///
368    /// # Panics
369    /// If the json object is not a [`Array`] variant
370    ///
371    /// [`Array`]: Json::Array
372    #[inline]
373    pub const fn expect_array_mut(&mut self) -> &mut [Json] {
374        self.array_mut().unwrap()
375    }
376
377    /// Attempts to get the inner boolean value of the json object, if
378    /// it is a True or False variant
379    #[inline]
380    pub const fn boolean(&self) -> Option<bool> {
381        if let Json::True = self {
382            Some(true)
383        } else if let Json::False = self {
384            Some(false)
385        } else {
386            None
387        }
388    }
389    /// Expects the json object to be a [`True`] or [`False`] variant
390    ///
391    /// # Panics
392    /// If the json object is not a [`True`] or [`False`] variant
393    ///
394    /// [`True`]: Json::True
395    /// [`False`]: Json::False
396    #[inline]
397    pub const fn expect_boolean(&self) -> bool {
398        self.boolean().unwrap()
399    }
400
401    /// Returns true if the json is a Nil variant
402    #[inline]
403    pub const fn is_null(&self) -> bool {
404        matches!(self, Json::Null)
405    }
406}
407
408impl fmt::Display for Json {
409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410        self.serialize(f)
411    }
412}
413
414macro_rules! from_num {
415    ( $( $nty:ty ),* ) => {
416        $(
417            impl From<$nty> for Json {
418                fn from(value: $nty) -> Self {
419                    Self::Number(value.into())
420                }
421            }
422
423            impl AddAssign<$nty> for Json {
424                fn add_assign(&mut self, rhs: $nty) {
425                    *self.expect_number_mut() += f64::from(rhs);
426                }
427            }
428
429            impl Add<$nty> for Json {
430                type Output = Json;
431
432                fn add(self, rhs: $nty) -> Self::Output {
433                    Json::Number(self.expect_number() + f64::from(rhs))
434                }
435            }
436
437            impl SubAssign<$nty> for Json {
438                fn sub_assign(&mut self, rhs: $nty) {
439                    *self.expect_number_mut() -= f64::from(rhs);
440                }
441            }
442
443            impl Sub<$nty> for Json {
444                type Output = Json;
445
446                fn sub(self, rhs: $nty) -> Self::Output {
447                    Json::Number(self.expect_number() - f64::from(rhs))
448                }
449            }
450
451            impl MulAssign<$nty> for Json {
452                fn mul_assign(&mut self, rhs: $nty) {
453                    *self.expect_number_mut() *= f64::from(rhs);
454                }
455            }
456
457            impl Mul<$nty> for Json {
458                type Output = Json;
459
460                fn mul(self, rhs: $nty) -> Self::Output {
461                    Json::Number(self.expect_number() * f64::from(rhs))
462                }
463            }
464
465            impl DivAssign<$nty> for Json {
466                fn div_assign(&mut self, rhs: $nty) {
467                    *self.expect_number_mut() /= f64::from(rhs);
468                }
469            }
470
471            impl Div<$nty> for Json {
472                type Output = Json;
473
474                fn div(self, rhs: $nty) -> Self::Output {
475                    Json::Number(self.expect_number() / f64::from(rhs))
476                }
477            }
478        )*
479    };
480}
481
482from_num!(f64, f32, i32, i16, u16, u8);
483
484impl From<String> for Json {
485    fn from(value: String) -> Self {
486        Self::String(value.into_boxed_str())
487    }
488}
489
490impl From<Box<str>> for Json {
491    fn from(value: Box<str>) -> Self {
492        Self::String(value)
493    }
494}
495
496impl<'a> From<&'a str> for Json {
497    fn from(value: &'a str) -> Self {
498        Self::String(value.into())
499    }
500}
501
502impl From<Vec<Json>> for Json {
503    fn from(value: Vec<Json>) -> Self {
504        Self::Array(value.into())
505    }
506}
507
508impl From<Map<Box<str>, Json>> for Json {
509    fn from(value: Map<Box<str>, Json>) -> Self {
510        Self::Object(value)
511    }
512}
513
514impl From<bool> for Json {
515    fn from(value: bool) -> Self {
516        if value { Json::True } else { Json::False }
517    }
518}
519
520impl Index<&str> for Json {
521    type Output = Json;
522
523    fn index(&self, index: &str) -> &Self::Output {
524        self.get(index).unwrap_or_else(|| {
525            panic!("Attemp to index a json element that doesn't contain the given key: '{index}'")
526        })
527    }
528}
529
530impl IndexMut<&str> for Json {
531    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
532        self.get_mut(index).unwrap_or_else(|| {
533            panic!("Attemp to index a json element that doesn't contain the given key: '{index}'")
534        })
535    }
536}
537
538impl Index<usize> for Json {
539    type Output = Json;
540
541    fn index(&self, index: usize) -> &Self::Output {
542        self.nth(index).unwrap_or_else(|| {
543            panic!("Attemp to index a json element that can't be indexed by {index}")
544        })
545    }
546}
547
548impl IndexMut<usize> for Json {
549    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
550        self.nth_mut(index).unwrap_or_else(|| {
551            panic!("Attemp to index a json element that can't be indexed by {index}")
552        })
553    }
554}
555
556#[doc(hidden)]
557pub use prelude::Map;
558
559/// Builds a [Json] object
560///
561/// # Example
562/// ```
563/// use json::json;
564///
565/// let j = json!({
566///     "hello" : ["w", 0, "r", "ld"],
567///     "array" : [
568///         { "key" : "val" },
569///         12.21,
570///         null,
571///         true,
572///         false
573///     ]
574/// });
575/// ```
576#[macro_export]
577macro_rules! json {
578    ( $lit:literal ) => {
579        $crate::Json::from( $lit )
580    };
581    ( { $e:expr } ) => {
582        $crate::Json::from( $e )
583    };
584    ( [ $( $e:tt ),* $(,)? ] ) => {
585        $crate::Json::from(
586            vec![
587                $(
588                    json!($e)
589                ),*
590            ]
591        )
592    };
593    ( { $( $key:literal : $val:tt ),* $(,)? } ) => {
594        {
595            let mut map = $crate::Map::new();
596            $( map.insert($key .into(), json!($val) );  )*
597            $crate::Json::from ( map )
598        }
599    };
600    ( null ) => {
601        $crate::Json::Null
602    }
603}