use super::parser::JsonParseError;
#[doc(alias = "json")]
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum JsonValue {
Null,
Bool(bool),
Number(f64),
String(String),
Array(Vec<JsonValue>),
Object(Vec<(String, JsonValue)>),
}
impl JsonValue {
#[must_use = "parsing may fail; handle the Result"]
pub fn parse(input: &str) -> Result<Self, JsonParseError> {
super::parser::parse(input)
}
#[must_use]
#[inline]
pub fn as_str(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_f64(&self) -> Option<f64> {
match self {
Self::Number(n) => Some(*n),
_ => None,
}
}
#[must_use]
#[inline]
#[allow(
clippy::cast_possible_truncation,
clippy::float_cmp,
clippy::cast_precision_loss
)]
pub fn as_i64(&self) -> Option<i64> {
match self {
Self::Number(n) => {
const MIN: f64 = -9_223_372_036_854_775_808.0; const LIMIT: f64 = 9_223_372_036_854_775_808.0; if n.is_finite() && n.fract() == 0.0 && *n >= MIN && *n < LIMIT {
return Some(*n as i64);
}
None
}
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_bool(&self) -> Option<bool> {
match self {
Self::Bool(b) => Some(*b),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_array(&self) -> Option<&[JsonValue]> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
#[must_use]
#[inline]
pub fn as_object(&self) -> Option<&[(String, JsonValue)]> {
match self {
Self::Object(o) => Some(o),
_ => None,
}
}
#[must_use]
#[inline]
pub fn get(&self, key: &str) -> Option<&JsonValue> {
match self {
Self::Object(entries) => entries.iter().find(|(k, _)| k == key).map(|(_, v)| v),
_ => None,
}
}
#[must_use]
#[inline]
pub fn get_str(&self, key: &str) -> Option<&str> {
self.get(key).and_then(Self::as_str)
}
#[must_use]
#[inline]
pub fn get_i64(&self, key: &str) -> Option<i64> {
self.get(key).and_then(Self::as_i64)
}
#[must_use]
#[inline]
pub fn get_bool(&self, key: &str) -> Option<bool> {
self.get(key).and_then(Self::as_bool)
}
#[must_use]
#[inline]
pub fn get_f64(&self, key: &str) -> Option<f64> {
self.get(key).and_then(Self::as_f64)
}
#[must_use]
#[inline]
pub fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
}