//! [`JsonValue`] DOM 及其辅助方法。 //! The [`JsonValue`] DOM and its helper methods. //! //! 对象使用 `Vec<(String, JsonValue)>` 保留插入顺序,而不是哈希表—— //! 这样序列化结果是确定性的,也与 provider 输出字段的顺序一致。 //! Objects preserve insertion order using a `Vec<(String, JsonValue)>` rather //! than a hash map, which keeps serialization deterministic and matches the //! order in which providers emit fields. use crate::error::{JsonError, JsonResult}; use std::fmt; /// [`JsonValue::entries`] 使用的私有双臂迭代器组合子。 /// Private two-arm iterator combinator used by [`JsonValue::entries`]. enum Either { Left(L), Right(R), } impl Iterator for Either where L: Iterator, R: Iterator, { type Item = I; fn next(&mut self) -> Option { match self { Either::Left(l) => l.next(), Either::Right(r) => r.next(), } } } /// 一个已解析的 JSON 值。 /// A parsed JSON value. #[derive(Debug, Clone, PartialEq, Default)] pub enum JsonValue { #[default] Null, Bool(bool), Num(f64), Str(String), Arr(Vec), /// 按插入顺序排列的键值对。 /// Key-value pairs in insertion order. Obj(Vec<(String, JsonValue)>), } impl JsonValue { // ---- 构造函数 ---- // ---- constructors ---------------------------------------------------- /// 创建一个空对象。 /// Create an empty object. pub fn obj() -> Self { JsonValue::Obj(Vec::new()) } /// 创建一个空数组。 /// Create an empty array. pub fn arr() -> Self { JsonValue::Arr(Vec::new()) } // ---- 判定 ---- // ---- predicates ------------------------------------------------------- /// 是否为 null。 /// Whether this is the null value. pub fn is_null(&self) -> bool { matches!(self, JsonValue::Null) } /// 是否为对象。 /// Whether this is an object. pub fn is_object(&self) -> bool { matches!(self, JsonValue::Obj(_)) } /// 是否为数组。 /// Whether this is an array. pub fn is_array(&self) -> bool { matches!(self, JsonValue::Arr(_)) } // ---- 访问器 ---- // ---- accessors -------------------------------------------------------- /// 按键从对象中获取字段。非对象返回 `None`。 /// Get a field from an object by key. Returns `None` for non-objects. pub fn get(&self, key: &str) -> Option<&JsonValue> { match self { JsonValue::Obj(entries) => entries.iter().find_map(|(k, v)| (k == key).then_some(v)), _ => None, } } /// 若字段为字符串,则以字符串切片借用。 /// Borrow a field as a string slice if it is a string. pub fn get_str(&self, key: &str) -> Option<&str> { match self.get(key)? { JsonValue::Str(s) => Some(s.as_str()), _ => None, } } /// 以布尔值借用字段。 /// Borrow a field as a bool. pub fn get_bool(&self, key: &str) -> Option { match self.get(key)? { JsonValue::Bool(b) => Some(*b), _ => None, } } /// 以数字借用字段。 /// Borrow a field as a number. pub fn get_num(&self, key: &str) -> Option { match self.get(key)? { JsonValue::Num(n) => Some(*n), _ => None, } } /// 以数组借用字段。 /// Borrow a field as an array. pub fn get_arr(&self, key: &str) -> Option<&Vec> { match self.get(key)? { JsonValue::Arr(a) => Some(a), _ => None, } } /// 以对象借用字段。 /// Borrow a field as an object. pub fn get_obj(&self, key: &str) -> Option<&Vec<(String, JsonValue)>> { match self.get(key)? { JsonValue::Obj(o) => Some(o), _ => None, } } /// 迭代对象的键值对;非对象返回空迭代器。 /// Iterate object entries. Empty for non-objects. pub fn entries(&self) -> impl Iterator { match self { JsonValue::Obj(entries) => Either::Left(entries.iter().map(|(k, v)| (k, v))), _ => Either::Right(std::iter::empty()), } } // ---- 修改器 ---- // ---- mutators --------------------------------------------------------- /// 向对象插入键值对;键已存在则替换。`self` 非对象时返回错误。 /// Insert a key-value pair into an object. Replaces if key exists. /// Returns an error if `self` is not an object. pub fn insert(&mut self, key: impl Into, value: JsonValue) -> JsonResult<()> { match self { JsonValue::Obj(entries) => { let key = key.into(); if let Some(slot) = entries.iter_mut().find(|(k, _)| *k == key) { slot.1 = value; } else { entries.push((key, value)); } Ok(()) } _ => Err(JsonError::new("cannot insert into non-object JsonValue")), } } /// 向数组追加一个值。`self` 非数组时返回错误。 /// Push a value into an array. Returns an error if `self` is not an array. pub fn push(&mut self, value: JsonValue) -> JsonResult<()> { match self { JsonValue::Arr(items) => { items.push(value); Ok(()) } _ => Err(JsonError::new("cannot push into non-array JsonValue")), } } } impl fmt::Display for JsonValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&crate::to_string(self)) } } // ---- 从基本类型的转换 ---- // ---- conversions from primitives ---------------------------------------- /// 从布尔值构造 JSON 值。 /// Construct a JSON value from a bool. impl From for JsonValue { fn from(b: bool) -> Self { JsonValue::Bool(b) } } /// 从字符串切片构造 JSON 值。 /// Construct a JSON value from a string slice. impl From<&str> for JsonValue { fn from(s: &str) -> Self { JsonValue::Str(s.to_string()) } } /// 从字符串构造 JSON 值。 /// Construct a JSON value from a String. impl From for JsonValue { fn from(s: String) -> Self { JsonValue::Str(s) } } /// 从 f64 构造 JSON 值。 /// Construct a JSON value from an f64. impl From for JsonValue { fn from(n: f64) -> Self { JsonValue::Num(n) } } /// 从 i64 构造 JSON 值(转为 f64 存储)。 /// Construct a JSON value from an i64 (stored as f64). impl From for JsonValue { fn from(n: i64) -> Self { JsonValue::Num(n as f64) } } /// 从 u64 构造 JSON 值(转为 f64 存储)。 /// Construct a JSON value from a u64 (stored as f64). impl From for JsonValue { fn from(n: u64) -> Self { JsonValue::Num(n as f64) } } /// 从 usize 构造 JSON 值(转为 f64 存储)。 /// Construct a JSON value from a usize (stored as f64). impl From for JsonValue { fn from(n: usize) -> Self { JsonValue::Num(n as f64) } } /// 从向量构造 JSON 数组(逐元素转换)。 /// Construct a JSON array from a vector (element-wise conversion). impl> From> for JsonValue { fn from(v: Vec) -> Self { JsonValue::Arr(v.into_iter().map(Into::into).collect()) } } #[cfg(test)] mod tests { use super::*; #[test] fn object_preserves_insertion_order() { let mut o = JsonValue::obj(); o.insert("b", JsonValue::Num(2.0)).unwrap(); o.insert("a", JsonValue::Num(1.0)).unwrap(); o.insert("c", JsonValue::Num(3.0)).unwrap(); let keys: Vec<_> = o.entries().map(|(k, _)| k.as_str()).collect(); assert_eq!(keys, vec!["b", "a", "c"]); } #[test] fn insert_replaces_existing_key() { let mut o = JsonValue::obj(); o.insert("x", JsonValue::Num(1.0)).unwrap(); o.insert("x", JsonValue::Num(2.0)).unwrap(); assert_eq!(o.get_num("x"), Some(2.0)); assert_eq!(o.entries().count(), 1); } #[test] fn accessors_return_none_for_wrong_types() { let s = JsonValue::Str("hi".into()); assert_eq!(s.get("x"), None); assert_eq!(s.get_str("x"), None); let mut o = JsonValue::obj(); o.insert("n", JsonValue::Num(1.0)).unwrap(); assert_eq!(o.get_str("n"), None); assert_eq!(o.get_num("n"), Some(1.0)); assert_eq!(o.get_str("missing"), None); } #[test] fn insert_into_array_errors() { let mut a = JsonValue::arr(); let res = a.insert("x", JsonValue::Null); assert!(res.is_err()); } #[test] fn push_into_object_errors() { let mut o = JsonValue::obj(); let res = o.push(JsonValue::Null); assert!(res.is_err()); } }