Skip to main content

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