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, "\"{s}\"")?;
156            }
157            Json::Number(n) => {
158                write!(out, "{n}")?;
159            }
160            Json::True => out.write_str("true")?,
161            Json::False => out.write_str("false")?,
162            Json::Null => out.write_str("null")?,
163        }
164        Ok(())
165    }
166    /// Attempts to get a value of the given json object.
167    /// If the json enum is not an Object variant, or if
168    /// it doesn't contain the key, returns None
169    #[inline]
170    pub fn get(&self, key: impl AsRef<str>) -> Option<&Json> {
171        self.object().and_then(|obj| obj.get(key.as_ref()))
172    }
173    /// Same as [get](Self::get), but with a mutable reference
174    #[inline]
175    pub fn get_mut(&mut self, key: impl AsRef<str>) -> Option<&mut Json> {
176        self.object_mut().and_then(|obj| obj.get_mut(key.as_ref()))
177    }
178    /// Attempts to get a value of the given json array.
179    /// If the json enum is not an Array variant, or if
180    /// it doesn't contain the key, returns None
181    #[inline]
182    pub fn nth(&self, i: usize) -> Option<&Json> {
183        self.array().and_then(|arr| arr.get(i))
184    }
185    /// Same as [nth](Self::nth), but with a mutable reference
186    #[inline]
187    pub fn nth_mut(&mut self, i: usize) -> Option<&mut Json> {
188        self.array_mut().and_then(|arr| arr.get_mut(i))
189    }
190
191    /// Attempts to get the inner [`Number`] of the json
192    /// object, if it is a [`Number`] variant
193    ///
194    /// [`Number`]: Json::Number
195    #[inline]
196    pub const fn number(&self) -> Option<f64> {
197        if let Json::Number(n) = self {
198            Some(*n)
199        } else {
200            None
201        }
202    }
203    /// Expects the json object to be a [`Number`] variant
204    ///
205    /// # Panics
206    /// If the json object is not a [`Number`] variant
207    ///
208    /// [`Number`]: Json::Number
209    #[inline]
210    pub const fn expect_number(&self) -> f64 {
211        self.number().unwrap()
212    }
213    /// Attempts to get a mutable reference to the inner [`Number`]
214    /// of the json object, if it is a [`Number`] variant
215    ///
216    /// [`Number`]: Json::Number
217    #[inline]
218    pub const fn number_mut(&mut self) -> Option<&mut f64> {
219        if let Json::Number(n) = self {
220            Some(n)
221        } else {
222            None
223        }
224    }
225    /// Expects the json object to be a [`Number`] variant
226    /// and gets a mutable reference to the inner number.
227    ///
228    /// # Panics
229    /// If the json object is not a [`Number`] variant
230    ///
231    /// [`Number`]: Json::Number
232    #[inline]
233    pub const fn expect_number_mut(&mut self) -> &mut f64 {
234        self.number_mut().unwrap()
235    }
236
237    /// Attempts to get the inner [`String`] of the json
238    /// object, if it is a [`String`] variant
239    ///
240    /// [`String`]: Json::String
241    #[inline]
242    pub const fn string(&self) -> Option<&str> {
243        if let Json::String(s) = self {
244            Some(s)
245        } else {
246            None
247        }
248    }
249    /// Expects the json object to be a [`String`] variant
250    ///
251    /// # Panics
252    /// If the json object is not a [`String`] variant
253    ///
254    /// [`String`]: Json::String
255    #[inline]
256    pub const fn expect_string(&self) -> &str {
257        self.string().unwrap()
258    }
259    /// Attempts to get a mutable reference to the inner
260    /// [`String`] of the json object, if it is a [`String`] variant
261    ///
262    /// [`String`]: Json::String
263    #[inline]
264    pub const fn string_mut(&mut self) -> Option<&mut str> {
265        if let Json::String(s) = self {
266            Some(s)
267        } else {
268            None
269        }
270    }
271    /// Expects the json object to be a [`String`] variant
272    /// and gets a reference to the inner string
273    ///
274    /// # Panics
275    /// If the json object is not a [`String`] variant
276    ///
277    /// [`String`]: Json::String
278    #[inline]
279    pub const fn expect_string_mut(&mut self) -> &mut str {
280        self.string_mut().unwrap()
281    }
282
283    /// Attempts to get the inner Object of the json object, if
284    /// it is an Object variant
285    #[inline]
286    pub const fn object(&self) -> Option<&Map<Box<str>, Json>> {
287        if let Json::Object(o) = self {
288            Some(o)
289        } else {
290            None
291        }
292    }
293    /// Expects the json object to be a [`Object`] variant
294    /// and gets a reference to the inner object
295    ///
296    /// # Panics
297    /// If the json object is not a [`Object`] variant
298    ///
299    /// [`Object`]: Json::Object
300    #[inline]
301    pub const fn expect_object(&self) -> &Map<Box<str>, Json> {
302        self.object().unwrap()
303    }
304    /// Attempts to get a mutable reference to the inner [`Object`] of
305    /// the json element, if it is an [`Object`] variant
306    ///
307    /// [`Object`]: Json::Object
308    #[inline]
309    pub const fn object_mut(&mut self) -> Option<&mut Map<Box<str>, Json>> {
310        if let Json::Object(o) = self {
311            Some(o)
312        } else {
313            None
314        }
315    }
316    /// Expects the json object to be a [`Object`] variant
317    /// and gets a mutable reference to the inner object
318    ///
319    /// # Panics
320    /// If the json object is not a [`Object`] variant
321    ///
322    /// [`Object`]: Json::Object
323    #[inline]
324    pub const fn expect_object_mut(&mut self) -> &mut Map<Box<str>, Json> {
325        self.object_mut().unwrap()
326    }
327
328    /// Attempts to get the inner Array of the json object, if
329    /// it is an Array variant
330    #[inline]
331    pub const fn array(&self) -> Option<&[Json]> {
332        if let Json::Array(o) = self {
333            Some(o)
334        } else {
335            None
336        }
337    }
338    /// Expects the json object to be a [`Array`] variant
339    ///
340    /// # Panics
341    /// If the json object is not a [`Array`] variant
342    ///
343    /// [`Array`]: Json::Array
344    #[inline]
345    pub const fn expect_array(&self) -> &[Json] {
346        self.array().unwrap()
347    }
348    /// Attempts to get the inner Array of the json object, if
349    /// it is an Array variant
350    #[inline]
351    pub const fn array_mut(&mut self) -> Option<&mut [Json]> {
352        if let Json::Array(o) = self {
353            Some(o)
354        } else {
355            None
356        }
357    }
358    /// Expects the json object to be a [`Array`] variant
359    ///
360    /// # Panics
361    /// If the json object is not a [`Array`] variant
362    ///
363    /// [`Array`]: Json::Array
364    #[inline]
365    pub const fn expect_array_mut(&mut self) -> &mut [Json] {
366        self.array_mut().unwrap()
367    }
368
369    /// Attempts to get the inner boolean value of the json object, if
370    /// it is a True or False variant
371    #[inline]
372    pub const fn boolean(&self) -> Option<bool> {
373        if let Json::True = self {
374            Some(true)
375        } else if let Json::False = self {
376            Some(false)
377        } else {
378            None
379        }
380    }
381    /// Expects the json object to be a [`True`] or [`False`] variant
382    ///
383    /// # Panics
384    /// If the json object is not a [`True`] or [`False`] variant
385    ///
386    /// [`True`]: Json::True
387    /// [`False`]: Json::False
388    #[inline]
389    pub const fn expect_boolean(&self) -> bool {
390        self.boolean().unwrap()
391    }
392
393    /// Returns true if the json is a Nil variant
394    #[inline]
395    pub const fn is_null(&self) -> bool {
396        matches!(self, Json::Null)
397    }
398}
399
400impl fmt::Display for Json {
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        self.serialize(f)
403    }
404}
405
406macro_rules! from_num {
407    ( $( $nty:ty ),* ) => {
408        $(
409            impl From<$nty> for Json {
410                fn from(value: $nty) -> Self {
411                    Self::Number(value.into())
412                }
413            }
414
415            impl AddAssign<$nty> for Json {
416                fn add_assign(&mut self, rhs: $nty) {
417                    *self.expect_number_mut() += f64::from(rhs);
418                }
419            }
420
421            impl Add<$nty> for Json {
422                type Output = Json;
423
424                fn add(self, rhs: $nty) -> Self::Output {
425                    Json::Number(self.expect_number() + f64::from(rhs))
426                }
427            }
428
429            impl SubAssign<$nty> for Json {
430                fn sub_assign(&mut self, rhs: $nty) {
431                    *self.expect_number_mut() -= f64::from(rhs);
432                }
433            }
434
435            impl Sub<$nty> for Json {
436                type Output = Json;
437
438                fn sub(self, rhs: $nty) -> Self::Output {
439                    Json::Number(self.expect_number() - f64::from(rhs))
440                }
441            }
442
443            impl MulAssign<$nty> for Json {
444                fn mul_assign(&mut self, rhs: $nty) {
445                    *self.expect_number_mut() *= f64::from(rhs);
446                }
447            }
448
449            impl Mul<$nty> for Json {
450                type Output = Json;
451
452                fn mul(self, rhs: $nty) -> Self::Output {
453                    Json::Number(self.expect_number() * f64::from(rhs))
454                }
455            }
456
457            impl DivAssign<$nty> for Json {
458                fn div_assign(&mut self, rhs: $nty) {
459                    *self.expect_number_mut() /= f64::from(rhs);
460                }
461            }
462
463            impl Div<$nty> for Json {
464                type Output = Json;
465
466                fn div(self, rhs: $nty) -> Self::Output {
467                    Json::Number(self.expect_number() / f64::from(rhs))
468                }
469            }
470        )*
471    };
472}
473
474from_num!(f64, f32, i32, i16, u16, u8);
475
476impl From<String> for Json {
477    fn from(value: String) -> Self {
478        Self::String(value.into_boxed_str())
479    }
480}
481
482impl From<Box<str>> for Json {
483    fn from(value: Box<str>) -> Self {
484        Self::String(value)
485    }
486}
487
488impl<'a> From<&'a str> for Json {
489    fn from(value: &'a str) -> Self {
490        Self::String(value.into())
491    }
492}
493
494impl From<Vec<Json>> for Json {
495    fn from(value: Vec<Json>) -> Self {
496        Self::Array(value.into())
497    }
498}
499
500impl From<Map<Box<str>, Json>> for Json {
501    fn from(value: Map<Box<str>, Json>) -> Self {
502        Self::Object(value)
503    }
504}
505
506impl From<bool> for Json {
507    fn from(value: bool) -> Self {
508        if value { Json::True } else { Json::False }
509    }
510}
511
512impl Index<&str> for Json {
513    type Output = Json;
514
515    fn index(&self, index: &str) -> &Self::Output {
516        self.get(index).unwrap_or_else(|| {
517            panic!("Attemp to index a json element that doesn't contain the given key: '{index}'")
518        })
519    }
520}
521
522impl IndexMut<&str> for Json {
523    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
524        self.get_mut(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 Index<usize> for Json {
531    type Output = Json;
532
533    fn index(&self, index: usize) -> &Self::Output {
534        self.nth(index).unwrap_or_else(|| {
535            panic!("Attemp to index a json element that can't be indexed by {index}")
536        })
537    }
538}
539
540impl IndexMut<usize> for Json {
541    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
542        self.nth_mut(index).unwrap_or_else(|| {
543            panic!("Attemp to index a json element that can't be indexed by {index}")
544        })
545    }
546}
547
548#[doc(hidden)]
549pub use prelude::Map;
550
551/// Builds a [Json] object
552///
553/// # Example
554/// ```
555/// use json::json;
556///
557/// let j = json!({
558///     "hello" : ["w", 0, "r", "ld"],
559///     "array" : [
560///         { "key" : "val" },
561///         12.21,
562///         null,
563///         true,
564///         false
565///     ]
566/// });
567/// ```
568#[macro_export]
569macro_rules! json {
570    ( $lit:literal ) => {
571        $crate::Json::from( $lit )
572    };
573    ( { $e:expr } ) => {
574        $crate::Json::from( $e )
575    };
576    ( [ $( $e:tt ),* $(,)? ] ) => {
577        $crate::Json::from(
578            vec![
579                $(
580                    json!($e)
581                ),*
582            ]
583        )
584    };
585    ( { $( $key:literal : $val:tt ),* $(,)? } ) => {
586        {
587            let mut map = $crate::Map::new();
588            $( map.insert($key .into(), json!($val) );  )*
589            $crate::Json::from ( map )
590        }
591    };
592    ( null ) => {
593        $crate::Json::Null
594    }
595}