json_syntax/
lib.rs

1//! This library provides a strict JSON parser as defined by
2//! [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) and
3//! [ECMA-404](https://www.ecma-international.org/publications-and-standards/standards/ecma-404/).
4//! Parsing values generates a [`CodeMap`] that keeps track of the position of
5//! each JSON value fragment in the parsed document.
6//!
7//! # Features
8//!
9//! - Strict implementation of [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) and
10//!   [ECMA-404](https://www.ecma-international.org/publications-and-standards/standards/ecma-404/).
11//! - No stack overflow, your memory is the limit.
12//! - Numbers are stored in lexical form thanks to the [`json-number`](https://crates.io/crates/json-number) crate,
13//!   their precision is not limited.
14//! - Duplicate values are preserved. A JSON object is just a list of entries,
15//!   in the order of definition.
16//! - Strings are stored on the stack whenever possible, thanks to the [`smallstr`](https://crates.io/crates/smallstr) crate.
17//! - The parser is configurable to accept documents that do not strictly
18//!   adhere to the standard.
19//! - Highly configurable printing methods.
20//! - Macro to build any value statically.
21//! - JSON Canonicalization Scheme implementation ([RFC 8785](https://www.rfc-editor.org/rfc/rfc8785))
22//!   enabled with the `canonicalization` feature.
23//! - `serde` support (by enabling the `serde` feature).
24//! - Conversion from/to `serde_json::Value` (by enabling the `serde_json` feature).
25//! - Thoroughly tested.
26//!
27//! # Usage
28//!
29//! ```
30//! use std::fs;
31//! use json_syntax::{Value, Parse, Print};
32//!
33//! let filename = "tests/inputs/y_structure_500_nested_arrays.json";
34//! let input = fs::read_to_string(filename).unwrap();
35//! let mut value = Value::parse_str(&input).expect("parse error").0;
36//! println!("value: {}", value.pretty_print());
37//! ```
38pub use json_number::{InvalidNumber, Number};
39use smallvec::SmallVec;
40use std::{fmt, str::FromStr};
41
42pub mod array;
43pub mod code_map;
44pub mod object;
45pub mod parse;
46mod unordered;
47pub use code_map::CodeMap;
48pub use parse::Parse;
49pub mod print;
50pub use print::Print;
51pub mod kind;
52pub use kind::{Kind, KindSet};
53mod convert;
54mod macros;
55mod try_from;
56pub use try_from::*;
57
58pub mod number {
59	pub use json_number::Buffer;
60}
61
62#[cfg(feature = "serde")]
63mod serde;
64
65#[cfg(feature = "serde")]
66pub use self::serde::*;
67
68pub use unordered::*;
69
70/// String stack capacity.
71///
72/// If a string is longer than this value,
73/// it will be stored on the heap.
74pub const SMALL_STRING_CAPACITY: usize = 16;
75
76/// String.
77pub type String = smallstr::SmallString<[u8; SMALL_STRING_CAPACITY]>;
78
79pub use array::Array;
80
81pub use object::Object;
82
83/// Number buffer stack capacity.
84///
85/// If the number is longer than this value,
86/// it will be stored on the heap.
87pub const NUMBER_CAPACITY: usize = SMALL_STRING_CAPACITY;
88
89/// Number buffer.
90pub type NumberBuf = json_number::SmallNumberBuf<NUMBER_CAPACITY>;
91
92/// JSON Value.
93///
94/// # Parsing
95///
96/// You can parse a `Value` by importing the [`Parse`] trait providing a
97/// collection of parsing functions.
98///
99/// ## Example
100///
101/// ```
102/// use json_syntax::{Value, Parse, CodeMap};
103/// let (value, code_map) = Value::parse_str("{ \"key\": \"value\" }").unwrap();
104/// ```
105///
106/// The `code_map` value of type [`CodeMap`] contains code-mapping information
107/// about all the fragments of the JSON value (their location in the source
108/// text).
109///
110/// # Comparison
111///
112/// This type implements the usual comparison traits `PartialEq`, `Eq`,
113/// `PartialOrd` and `Ord`. However by default JSON object entries ordering
114/// matters, meaning that `{ "a": 0, "b": 1 }` is **not** equal to
115/// `{ "b": 1, "a": 0 }`.
116/// If you want to do comparisons while ignoring entries ordering, you can use
117/// the [`Unordered`] type (combined with the [`UnorderedPartialEq`] trait).
118/// Any `T` reference can be turned into an [`Unordered<T>`] reference
119/// at will using the [`BorrowUnordered::as_unordered`] method.
120///
121/// ## Example
122///
123/// ```
124/// use json_syntax::{json, Unordered, BorrowUnordered};
125///
126/// let a = json!({ "a": 0, "b": 1 });
127/// let b = json!({ "b": 1, "a": 0 });
128///
129/// assert_ne!(a, b); // not equals entries are in a different order.
130/// assert_eq!(a.as_unordered(), b.as_unordered()); // equals modulo entry order.
131/// assert_eq!(Unordered(a), Unordered(b)); // equals modulo entry order.
132/// ```
133///
134/// # Printing
135///
136/// The [`Print`] trait provide a highly configurable printing method.
137///
138/// ## Example
139///
140/// ```
141/// use json_syntax::{Value, Parse, Print};
142///
143/// let value = Value::parse_str("[ 0, 1, { \"key\": \"value\" }, null ]").unwrap().0;
144///
145/// println!("{}", value.pretty_print()); // multi line, indent with 2 spaces
146/// println!("{}", value.inline_print()); // single line, spaces
147/// println!("{}", value.compact_print()); // single line, no spaces
148///
149/// let mut options = json_syntax::print::Options::pretty();
150/// options.indent = json_syntax::print::Indent::Tabs(1);
151/// println!("{}", value.print_with(options)); // multi line, indent with tabs
152/// ```
153#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
154pub enum Value {
155	/// `null`.
156	Null,
157
158	/// Boolean `true` or `false`.
159	Boolean(bool),
160
161	/// Number.
162	Number(NumberBuf),
163
164	/// String.
165	String(String),
166
167	/// Array.
168	Array(Array),
169
170	/// Object.
171	Object(Object),
172}
173
174pub fn get_array_fragment(array: &[Value], mut index: usize) -> Result<FragmentRef, usize> {
175	for v in array {
176		match v.get_fragment(index) {
177			Ok(value) => return Ok(value),
178			Err(i) => index = i,
179		}
180	}
181
182	Err(index)
183}
184
185impl Value {
186	pub fn get_fragment(&self, index: usize) -> Result<FragmentRef, usize> {
187		if index == 0 {
188			Ok(FragmentRef::Value(self))
189		} else {
190			match self {
191				Self::Array(a) => get_array_fragment(a, index - 1),
192				Self::Object(o) => o.get_fragment(index - 1),
193				_ => Err(index - 1),
194			}
195		}
196	}
197
198	#[inline]
199	pub fn kind(&self) -> Kind {
200		match self {
201			Self::Null => Kind::Null,
202			Self::Boolean(_) => Kind::Boolean,
203			Self::Number(_) => Kind::Number,
204			Self::String(_) => Kind::String,
205			Self::Array(_) => Kind::Array,
206			Self::Object(_) => Kind::Object,
207		}
208	}
209
210	#[inline]
211	pub fn is_kind(&self, kind: Kind) -> bool {
212		self.kind() == kind
213	}
214
215	#[inline]
216	pub fn is_null(&self) -> bool {
217		matches!(self, Self::Null)
218	}
219
220	#[inline]
221	pub fn is_boolean(&self) -> bool {
222		matches!(self, Self::Boolean(_))
223	}
224
225	#[inline]
226	pub fn is_number(&self) -> bool {
227		matches!(self, Self::Number(_))
228	}
229
230	#[inline]
231	pub fn is_string(&self) -> bool {
232		matches!(self, Self::String(_))
233	}
234
235	#[inline]
236	pub fn is_array(&self) -> bool {
237		matches!(self, Self::Array(_))
238	}
239
240	#[inline]
241	pub fn is_object(&self) -> bool {
242		matches!(self, Self::Object(_))
243	}
244
245	/// Checks if the value is either an empty array or an empty object.
246	#[inline]
247	pub fn is_empty_array_or_object(&self) -> bool {
248		match self {
249			Self::Array(a) => a.is_empty(),
250			Self::Object(o) => o.is_empty(),
251			_ => false,
252		}
253	}
254
255	#[inline]
256	pub fn as_boolean(&self) -> Option<bool> {
257		match self {
258			Self::Boolean(b) => Some(*b),
259			_ => None,
260		}
261	}
262
263	#[inline]
264	pub fn as_boolean_mut(&mut self) -> Option<&mut bool> {
265		match self {
266			Self::Boolean(b) => Some(b),
267			_ => None,
268		}
269	}
270
271	#[inline]
272	pub fn as_number(&self) -> Option<&Number> {
273		match self {
274			Self::Number(n) => Some(n),
275			_ => None,
276		}
277	}
278
279	#[inline]
280	pub fn as_number_mut(&mut self) -> Option<&mut NumberBuf> {
281		match self {
282			Self::Number(n) => Some(n),
283			_ => None,
284		}
285	}
286
287	#[inline]
288	pub fn as_string(&self) -> Option<&str> {
289		match self {
290			Self::String(s) => Some(s),
291			_ => None,
292		}
293	}
294
295	/// Alias for [`as_string`](Self::as_string).
296	#[inline]
297	pub fn as_str(&self) -> Option<&str> {
298		self.as_string()
299	}
300
301	#[inline]
302	pub fn as_string_mut(&mut self) -> Option<&mut String> {
303		match self {
304			Self::String(s) => Some(s),
305			_ => None,
306		}
307	}
308
309	#[inline]
310	pub fn as_array(&self) -> Option<&[Self]> {
311		match self {
312			Self::Array(a) => Some(a),
313			_ => None,
314		}
315	}
316
317	#[inline]
318	pub fn as_array_mut(&mut self) -> Option<&mut Array> {
319		match self {
320			Self::Array(a) => Some(a),
321			_ => None,
322		}
323	}
324
325	/// Return the given value as an array, even if it is not an array.
326	///
327	/// Returns the input value as is if it is already an array,
328	/// or puts it in a slice with a single element if it is not.
329	#[inline]
330	pub fn force_as_array(&self) -> &[Self] {
331		match self {
332			Self::Array(a) => a,
333			other => core::slice::from_ref(other),
334		}
335	}
336
337	#[inline]
338	pub fn as_object(&self) -> Option<&Object> {
339		match self {
340			Self::Object(o) => Some(o),
341			_ => None,
342		}
343	}
344
345	#[inline]
346	pub fn as_object_mut(&mut self) -> Option<&mut Object> {
347		match self {
348			Self::Object(o) => Some(o),
349			_ => None,
350		}
351	}
352
353	#[inline]
354	pub fn into_boolean(self) -> Option<bool> {
355		match self {
356			Self::Boolean(b) => Some(b),
357			_ => None,
358		}
359	}
360
361	#[inline]
362	pub fn into_number(self) -> Option<NumberBuf> {
363		match self {
364			Self::Number(n) => Some(n),
365			_ => None,
366		}
367	}
368
369	#[inline]
370	pub fn into_string(self) -> Option<String> {
371		match self {
372			Self::String(s) => Some(s),
373			_ => None,
374		}
375	}
376
377	#[inline]
378	pub fn into_array(self) -> Option<Array> {
379		match self {
380			Self::Array(a) => Some(a),
381			_ => None,
382		}
383	}
384
385	#[inline]
386	pub fn into_object(self) -> Option<Object> {
387		match self {
388			Self::Object(o) => Some(o),
389			_ => None,
390		}
391	}
392
393	pub fn traverse(&self) -> Traverse {
394		let mut stack = SmallVec::new();
395		stack.push(FragmentRef::Value(self));
396		Traverse { offset: 0, stack }
397	}
398
399	/// Recursively count the number of values for which `f` returns `true`.
400	pub fn count(&self, mut f: impl FnMut(usize, FragmentRef) -> bool) -> usize {
401		self.traverse().filter(|(i, q)| f(*i, *q)).count()
402	}
403
404	/// Returns the volume of the value.
405	///
406	/// The volume is the sum of all values and recursively nested values
407	/// included in `self`, including `self` (the volume is at least `1`).
408	///
409	/// This is equivalent to `value.traverse().filter(|(_, f)| f.is_value()).count()`.
410	pub fn volume(&self) -> usize {
411		self.traverse().filter(|(_, f)| f.is_value()).count()
412	}
413
414	/// Move and return the value, leaves `null` in its place.
415	#[inline(always)]
416	pub fn take(&mut self) -> Self {
417		let mut result = Self::Null;
418		std::mem::swap(&mut result, self);
419		result
420	}
421
422	/// Puts this JSON value in canonical form according to
423	/// [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785).
424	///
425	/// The given `buffer` is used to canonicalize the number values.
426	#[cfg(feature = "canonicalize")]
427	pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
428		match self {
429			Self::Number(n) => *n = NumberBuf::from_number(n.canonical_with(buffer)),
430			Self::Array(a) => {
431				for item in a {
432					item.canonicalize_with(buffer)
433				}
434			}
435			Self::Object(o) => o.canonicalize_with(buffer),
436			_ => (),
437		}
438	}
439
440	/// Puts this JSON value in canonical form according to
441	/// [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785).
442	#[cfg(feature = "canonicalize")]
443	pub fn canonicalize(&mut self) {
444		let mut buffer = ryu_js::Buffer::new();
445		self.canonicalize_with(&mut buffer)
446	}
447}
448
449impl UnorderedPartialEq for Value {
450	fn unordered_eq(&self, other: &Self) -> bool {
451		match (self, other) {
452			(Self::Null, Self::Null) => true,
453			(Self::Boolean(a), Self::Boolean(b)) => a == b,
454			(Self::Number(a), Self::Number(b)) => a == b,
455			(Self::String(a), Self::String(b)) => a == b,
456			(Self::Array(a), Self::Array(b)) => a.unordered_eq(b),
457			(Self::Object(a), Self::Object(b)) => a.unordered_eq(b),
458			_ => false,
459		}
460	}
461}
462
463impl UnorderedEq for Value {}
464
465impl fmt::Display for Value {
466	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467		self.compact_print().fmt(f)
468	}
469}
470
471impl From<Value> for ::std::string::String {
472	fn from(value: Value) -> Self {
473		value.to_string()
474	}
475}
476
477impl From<bool> for Value {
478	fn from(b: bool) -> Self {
479		Self::Boolean(b)
480	}
481}
482
483impl From<NumberBuf> for Value {
484	fn from(n: NumberBuf) -> Self {
485		Self::Number(n)
486	}
487}
488
489impl<'n> From<&'n Number> for Value {
490	fn from(n: &'n Number) -> Self {
491		Self::Number(unsafe { NumberBuf::new_unchecked(n.as_bytes().into()) })
492	}
493}
494
495impl From<String> for Value {
496	fn from(s: String) -> Self {
497		Self::String(s)
498	}
499}
500
501impl From<::std::string::String> for Value {
502	fn from(s: ::std::string::String) -> Self {
503		Self::String(s.into())
504	}
505}
506
507impl<'s> From<&'s str> for Value {
508	fn from(s: &'s str) -> Self {
509		Self::String(s.into())
510	}
511}
512
513impl From<Array> for Value {
514	fn from(a: Array) -> Self {
515		Self::Array(a)
516	}
517}
518
519impl From<Object> for Value {
520	fn from(o: Object) -> Self {
521		Self::Object(o)
522	}
523}
524
525impl FromStr for Value {
526	type Err = parse::Error;
527
528	fn from_str(s: &str) -> Result<Self, Self::Err> {
529		Ok(Self::parse_str(s)?.0)
530	}
531}
532
533macro_rules! from_integer {
534	($($ty:ident),*) => {
535		$(
536			impl From<$ty> for Value {
537				fn from(n: $ty) -> Self {
538					Value::Number(n.into())
539				}
540			}
541		)*
542	};
543}
544
545from_integer! {
546	u8,
547	u16,
548	u32,
549	u64,
550	i8,
551	i16,
552	i32,
553	i64
554}
555
556macro_rules! try_from_float {
557	($($ty:ident),*) => {
558		$(
559			impl TryFrom<$ty> for Value {
560				type Error = json_number::TryFromFloatError;
561
562				fn try_from(n: $ty) -> Result<Self, Self::Error> {
563					Ok(Value::Number(n.try_into()?))
564				}
565			}
566		)*
567	};
568}
569
570try_from_float! {
571	f32,
572	f64
573}
574
575pub enum FragmentRef<'a> {
576	Value(&'a Value),
577	Entry(&'a object::Entry),
578	Key(&'a object::Key),
579}
580
581impl<'a> FragmentRef<'a> {
582	pub fn is_entry(&self) -> bool {
583		matches!(self, Self::Entry(_))
584	}
585
586	pub fn is_key(&self) -> bool {
587		matches!(self, Self::Key(_))
588	}
589
590	pub fn is_value(&self) -> bool {
591		matches!(self, Self::Value(_))
592	}
593
594	pub fn is_null(&self) -> bool {
595		matches!(self, Self::Value(Value::Null))
596	}
597
598	pub fn is_number(&self) -> bool {
599		matches!(self, Self::Value(Value::Number(_)))
600	}
601
602	pub fn is_string(&self) -> bool {
603		matches!(self, Self::Value(Value::String(_)))
604	}
605
606	pub fn is_array(&self) -> bool {
607		matches!(self, Self::Value(Value::Array(_)))
608	}
609
610	pub fn is_object(&self) -> bool {
611		matches!(self, Self::Value(Value::Object(_)))
612	}
613
614	pub fn strip(self) -> FragmentRef<'a> {
615		match self {
616			Self::Value(v) => FragmentRef::Value(v),
617			Self::Entry(e) => FragmentRef::Entry(e),
618			Self::Key(k) => FragmentRef::Key(k),
619		}
620	}
621}
622
623impl<'a> Clone for FragmentRef<'a> {
624	fn clone(&self) -> Self {
625		*self
626	}
627}
628
629impl<'a> Copy for FragmentRef<'a> {}
630
631impl<'a> FragmentRef<'a> {
632	pub fn sub_fragments(&self) -> SubFragments<'a> {
633		match self {
634			Self::Value(Value::Array(a)) => SubFragments::Array(a.iter()),
635			Self::Value(Value::Object(o)) => SubFragments::Object(o.iter()),
636			Self::Entry(e) => SubFragments::Entry(Some(&e.key), Some(&e.value)),
637			_ => SubFragments::None,
638		}
639	}
640}
641
642pub enum SubFragments<'a> {
643	None,
644	Array(core::slice::Iter<'a, Value>),
645	Object(core::slice::Iter<'a, object::Entry>),
646	Entry(Option<&'a object::Key>, Option<&'a Value>),
647}
648
649impl<'a> Iterator for SubFragments<'a> {
650	type Item = FragmentRef<'a>;
651
652	fn next(&mut self) -> Option<Self::Item> {
653		match self {
654			Self::None => None,
655			Self::Array(a) => a.next().map(FragmentRef::Value),
656			Self::Object(e) => e.next().map(FragmentRef::Entry),
657			Self::Entry(k, v) => k
658				.take()
659				.map(FragmentRef::Key)
660				.or_else(|| v.take().map(FragmentRef::Value)),
661		}
662	}
663}
664
665impl<'a> DoubleEndedIterator for SubFragments<'a> {
666	fn next_back(&mut self) -> Option<Self::Item> {
667		match self {
668			Self::None => None,
669			Self::Array(a) => a.next_back().map(FragmentRef::Value),
670			Self::Object(e) => e.next_back().map(FragmentRef::Entry),
671			Self::Entry(k, v) => v
672				.take()
673				.map(FragmentRef::Value)
674				.or_else(|| k.take().map(FragmentRef::Key)),
675		}
676	}
677}
678
679pub struct Traverse<'a> {
680	offset: usize,
681	stack: SmallVec<[FragmentRef<'a>; 8]>,
682}
683
684impl<'a> Iterator for Traverse<'a> {
685	type Item = (usize, FragmentRef<'a>);
686
687	fn next(&mut self) -> Option<Self::Item> {
688		match self.stack.pop() {
689			Some(v) => {
690				self.stack.extend(v.sub_fragments().rev());
691				let i = self.offset;
692				self.offset += 1;
693				Some((i, v))
694			}
695			None => None,
696		}
697	}
698}
699
700#[cfg(test)]
701mod tests {
702	#[cfg(feature = "canonicalize")]
703	#[test]
704	fn canonicalize_01() {
705		use super::*;
706		let mut value: Value = json!({
707			"b": 0.00000000001,
708			"c": {
709				"foo": true,
710				"bar": false
711			},
712			"a": [ "foo", "bar" ]
713		});
714
715		value.canonicalize();
716
717		assert_eq!(
718			value.compact_print().to_string(),
719			"{\"a\":[\"foo\",\"bar\"],\"b\":1e-11,\"c\":{\"bar\":false,\"foo\":true}}"
720		)
721	}
722
723	#[cfg(feature = "canonicalize")]
724	#[test]
725	fn canonicalize_02() {
726		use super::*;
727		let (mut value, _) = Value::parse_str(
728			"{
729			\"numbers\": [333333333.33333329, 1E30, 4.50, 2e-3, 0.000000000000000000000000001],
730			\"string\": \"\\u20ac$\\u000F\\u000aA'\\u0042\\u0022\\u005c\\\\\\\"\\/\",
731			\"literals\": [null, true, false]
732		}",
733		)
734		.unwrap();
735
736		value.canonicalize();
737
738		assert_eq!(
739			value.compact_print().to_string(),
740			"{\"literals\":[null,true,false],\"numbers\":[333333333.3333333,1e+30,4.5,0.002,1e-27],\"string\":\"€$\\u000f\\nA'B\\\"\\\\\\\\\\\"/\"}"
741		)
742	}
743}