Enum json_syntax::Value

source ·
pub enum Value<M = ()> {
    Null,
    Boolean(bool),
    Number(NumberBuf),
    String(String),
    Array(Array<M>),
    Object(Object<M>),
}
Expand description

Value.

The type parameter M is the type of metadata attached to each syntax node (values, sub values and object keys). The metadata is derived from the locspan::Span of the node in the source document using the metadata builder function passed to the parsing function (see the Parse trait for more details).

Parsing

You can parse a Value by importing the Parse trait providing a collection of parsing functions.

Example

use json_syntax::{Value, Parse};
use locspan::{Meta, Span};

let value: Meta<Value<Span>, Span> = Value::parse_str("{ \"key\": \"value\" }", |span| span).unwrap();

You don’t need to specify the return type, here only shown to make it clear. Furthermore the MetaValue<Span> type alias can be used instead of Meta<Value<Span>, Span> to avoid repetition of the metadata type.

Comparison

This type implements the usual comparison traits PartialEq, Eq, PartialOrd and Ord. However these implementations will also compare the metadata. If you want to do comparisons while ignoring ths metadata, you can use the locspan::Stripped type (combined with the locspan::BorrowStripped trait).

Example

use json_syntax::{Value, Parse};
use locspan::BorrowStripped;

let a = Value::parse_str("null", |_| 0).unwrap();
let b = Value::parse_str("null", |_| 1).unwrap();

assert_ne!(a, b); // not equals because the metadata is different.
assert_eq!(a.stripped(), b.stripped()); // equals because the metadata is ignored.

Printing

The Print trait provide a highly configurable printing method.

Example

use json_syntax::{Value, Parse, Print};

let value = Value::parse_str("[ 0, 1, { \"key\": \"value\" }, null ]", |span| span).unwrap();

println!("{}", value.pretty_print()); // multi line, indent with 2 spaces
println!("{}", value.inline_print()); // single line, spaces
println!("{}", value.compact_print()); // single line, no spaces

let mut options = json_syntax::print::Options::pretty();
options.indent = json_syntax::print::Indent::Tabs(1);
println!("{}", value.print_with(options)); // multi line, indent with tabs

Variants§

§

Null

null.

§

Boolean(bool)

Boolean true or false.

§

Number(NumberBuf)

Number.

§

String(String)

String.

§

Array(Array<M>)

Array.

§

Object(Object<M>)

Object.

Implementations§

Converts a serde_json::Value into a Value.

The function f is used to annotate the output each sub value (passed as parameter).

Examples found in repository?
src/convert/serde_json.rs (line 31)
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
	pub fn from_serde_json(
		value: serde_json::Value,
		f: impl Clone + Fn(SerdeJsonFragment) -> M,
	) -> Meta<Self, M> {
		let meta = f(SerdeJsonFragment::Value(&value));

		let v = match value {
			serde_json::Value::Null => Self::Null,
			serde_json::Value::Bool(b) => Self::Boolean(b),
			serde_json::Value::Number(n) => Self::Number(n.into()),
			serde_json::Value::String(s) => Self::String(s.into()),
			serde_json::Value::Array(a) => Self::Array(
				a.into_iter()
					.map(|i| Self::from_serde_json(i, f.clone()))
					.collect(),
			),
			serde_json::Value::Object(o) => Self::Object(
				o.into_iter()
					.map(|(k, v)| {
						let k_meta = f(SerdeJsonFragment::Key(&k));
						Entry::new(Meta(k.into(), k_meta), Self::from_serde_json(v, f.clone()))
					})
					.collect(),
			),
		};

		Meta(v, meta)
	}

	/// Converts a `Value` into a [`serde_json::Value`], stripping the metadata.
	pub fn into_serde_json(Meta(this, _): Meta<Self, M>) -> serde_json::Value {
		this.into()
	}
}

impl<M: Default> From<serde_json::Value> for Value<M> {
	#[inline(always)]
	fn from(value: serde_json::Value) -> Self {
		Value::from_serde_json(value, |_| M::default()).into_value()
	}

Converts a Value into a serde_json::Value, stripping the metadata.

Examples found in repository?
src/convert/serde_json.rs (line 74)
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
	fn from(value: Value<M>) -> Self {
		match value {
			Value::Null => Self::Null,
			Value::Boolean(b) => Self::Bool(b),
			Value::Number(n) => Self::Number(n.into()),
			Value::String(s) => Self::String(s.into_string()),
			Value::Array(a) => Self::Array(a.into_iter().map(Value::into_serde_json).collect()),
			Value::Object(o) => Self::Object(
				o.into_iter()
					.map(
						|Entry {
						     key: Meta(key, _),
						     value,
						 }| { (key.into_string(), Value::into_serde_json(value)) },
					)
					.collect(),
			),
		}
	}
Examples found in repository?
src/lib.rs (line 233)
232
233
234
	pub fn is_kind(&self, kind: Kind) -> bool {
		self.kind() == kind
	}

Checks if the value is either an empty array or an empty object.

Examples found in repository?
src/lib.rs (line 319)
318
319
320
	pub fn as_str(&self) -> Option<&str> {
		self.as_string()
	}

Alias for as_string.

Return the given value as an array, even if it is not an array.

Returns the input value as is if it is already an array, or puts it in a slice with a single element if it is not.

Examples found in repository?
src/lib.rs (line 422)
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
	pub fn count(&self, mut f: impl FnMut(StrippedFragmentRef<M>) -> bool) -> usize {
		self.traverse().filter(|i| f(*i)).count()
	}

	/// Returns the volume of the value.
	///
	/// The volume is the sum of all values and recursively nested values
	/// included in `self`, including `self` (the volume is at least `1`).
	///
	/// This is equivalent to `value.traverse().filter(StrippedFragmentRef::is_value).count()`.
	pub fn volume(&self) -> usize {
		self.traverse()
			.filter(StrippedFragmentRef::is_value)
			.count()
	}

Recursively count the number of values for which f returns true.

Examples found in repository?
src/print.rs (line 799)
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
	fn fmt_with(&self, f: &mut fmt::Formatter, options: &Options, indent: usize) -> fmt::Result {
		match self {
			Self::Null => f.write_str("null"),
			Self::Boolean(b) => b.fmt_with(f, options, indent),
			Self::Number(n) => n.fmt_with(f, options, indent),
			Self::String(s) => s.fmt_with(f, options, indent),
			Self::Array(a) => {
				let mut sizes = Vec::with_capacity(self.count(|v| v.is_array() || v.is_object()));
				self.pre_compute_size(options, &mut sizes);
				let mut index = 0;
				a.fmt_with_size(f, options, indent, &sizes, &mut index)
			}
			Self::Object(o) => {
				let mut sizes = Vec::with_capacity(self.count(|v| v.is_array() || v.is_object()));
				self.pre_compute_size(options, &mut sizes);
				let mut index = 0;
				o.fmt_with_size(f, options, indent, &sizes, &mut index)
			}
		}
	}

Returns the volume of the value.

The volume is the sum of all values and recursively nested values included in self, including self (the volume is at least 1).

This is equivalent to value.traverse().filter(StrippedFragmentRef::is_value).count().

Recursively maps the metadata inside the value.

Examples found in repository?
src/lib.rs (line 446)
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
	pub fn map_metadata<N>(self, mut f: impl FnMut(M) -> N) -> Value<N> {
		match self {
			Self::Null => Value::Null,
			Self::Boolean(b) => Value::Boolean(b),
			Self::Number(n) => Value::Number(n),
			Self::String(s) => Value::String(s),
			Self::Array(a) => Value::Array(
				a.into_iter()
					.map(|Meta(item, meta)| Meta(item.map_metadata(&mut f), f(meta)))
					.collect(),
			),
			Self::Object(o) => Value::Object(o.map_metadata(f)),
		}
	}

	/// Tries to recursively maps the metadata inside the value.
	pub fn try_map_metadata<N, E>(
		self,
		mut f: impl FnMut(M) -> Result<N, E>,
	) -> Result<Value<N>, E> {
		match self {
			Self::Null => Ok(Value::Null),
			Self::Boolean(b) => Ok(Value::Boolean(b)),
			Self::Number(n) => Ok(Value::Number(n)),
			Self::String(s) => Ok(Value::String(s)),
			Self::Array(a) => {
				let mut items = Vec::with_capacity(a.len());
				for item in a {
					items.push(item.try_map_metadata_recursively(&mut f)?)
				}
				Ok(Value::Array(items))
			}
			Self::Object(o) => Ok(Value::Object(o.try_map_metadata(f)?)),
		}
	}

	/// Move and return the value, leaves `null` in its place.
	#[inline(always)]
	pub fn take(&mut self) -> Self {
		let mut result = Self::Null;
		std::mem::swap(&mut result, self);
		result
	}

	/// Puts this JSON value in canonical form according to
	/// [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785).
	///
	/// The given `buffer` is used to canonicalize the number values.
	#[cfg(feature = "canonicalize")]
	pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
		match self {
			Self::Number(n) => *n = NumberBuf::from_number(n.canonical_with(buffer)),
			Self::Array(a) => {
				for item in a {
					item.canonicalize_with(buffer)
				}
			}
			Self::Object(o) => o.canonicalize_with(buffer),
			_ => (),
		}
	}

	/// Puts this JSON value in canonical form according to
	/// [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785).
	#[cfg(feature = "canonicalize")]
	pub fn canonicalize(&mut self) {
		let mut buffer = ryu_js::Buffer::new();
		self.canonicalize_with(&mut buffer)
	}
}

pub trait Traversal<'a> {
	type Fragment;
	type Traverse: Iterator<Item = Self::Fragment>;

	fn traverse(&'a self) -> Self::Traverse;
}

impl<'a, M: 'a> Traversal<'a> for Meta<Value<M>, M> {
	type Fragment = FragmentRef<'a, M>;
	type Traverse = Traverse<'a, M>;

	fn traverse(&'a self) -> Self::Traverse {
		let mut stack = SmallVec::new();
		stack.push(FragmentRef::Value(self));
		Traverse { stack }
	}
}

impl<M, N> locspan::MapMetadataRecursively<M, N> for Value<M> {
	type Output = Value<N>;

	fn map_metadata_recursively<F: FnMut(M) -> N>(self, f: F) -> Value<N> {
		self.map_metadata(f)
	}

Tries to recursively maps the metadata inside the value.

Examples found in repository?
src/lib.rs (line 542)
538
539
540
541
542
543
	fn try_map_metadata_recursively<F: FnMut(M) -> Result<N, E>>(
		self,
		f: F,
	) -> Result<Value<N>, E> {
		self.try_map_metadata(f)
	}

Move and return the value, leaves null in its place.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Maps the metadata, recursively.
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Print the value with Options::pretty options.
Print the value with Options::compact options.
Print the value with Options::inline options.
Print the value with the given options.
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
Tries to map the metadata, recursively.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Wraps self inside a Meta<Self, M> using the given metadata. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Compare self to key and return true if they are equal.

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.