From a09159c987be7cbd6181daa8f1e616517a38e727 Mon Sep 17 00:00:00 2001 From: Vraj Shah Date: Sat, 26 Apr 2025 11:58:33 -0400 Subject: [PATCH 1/2] Added valuable in cargo.toml --- Cargo.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 866c31318..2d602fecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "serde_json" version = "1.0.140" -authors = ["Erick Tryzelaar ", "David Tolnay "] +authors = [ + "Erick Tryzelaar ", + "David Tolnay ", +] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" documentation = "https://docs.rs/serde_json" @@ -17,6 +20,7 @@ itoa = "1.0" memchr = { version = "2", default-features = false } ryu = "1.0" serde = { version = "1.0.194", default-features = false } +valuable = { version = "0.1.1", optional = true } [dev-dependencies] automod = "1.0.11" @@ -89,3 +93,6 @@ raw_value = [] # overflow the stack after deserialization has completed, including, but not # limited to, Display and Debug and Drop impls. unbounded_depth = [] + +# Implement the valuable trait for serde_json::Value +valuable = ["dep:valuable"] From 7ba998d41456477d3297e7316820b16e399a349a Mon Sep 17 00:00:00 2001 From: Vraj Shah Date: Sat, 26 Apr 2025 12:06:46 -0400 Subject: [PATCH 2/2] Added valuable support --- src/lib.rs | 3 ++ src/valuable.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/valuable.rs diff --git a/src/lib.rs b/src/lib.rs index a9f82f2b3..70221d2d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,3 +435,6 @@ mod read; #[cfg(feature = "raw_value")] mod raw; + +#[cfg(feature = "valuable")] +mod valuable; diff --git a/src/valuable.rs b/src/valuable.rs new file mode 100644 index 000000000..3cba28b79 --- /dev/null +++ b/src/valuable.rs @@ -0,0 +1,79 @@ +use crate::{Map, Value as Json}; +use alloc::string::String; + +use valuable::{Mappable, Valuable, Value, Visit}; + +impl Valuable for Json { + fn as_value(&self) -> Value<'_> { + match self { + Json::Array(ref array) => array.as_value(), + Json::Bool(ref value) => value.as_value(), + Json::Number(ref num) => { + if num.is_f64() { + Value::F64(num.as_f64().unwrap()) + } else if num.is_i64() { + Value::I64(num.as_i64().unwrap()) + } else { + unreachable!() + } + } + Json::Null => Value::Unit, + Json::String(ref s) => s.as_value(), + Json::Object(ref object) => object.as_value(), + } + } + + fn visit(&self, visit: &mut dyn Visit) { + match self { + Json::Array(ref array) => array.visit(visit), + Json::Bool(ref value) => value.visit(visit), + Json::Number(ref num) => { + if num.is_f64() { + num.as_f64().unwrap().visit(visit) + } else if num.is_i64() { + num.as_i64().unwrap().visit(visit) + } else { + unreachable!() + } + } + Json::Null => Value::Unit.visit(visit), + Json::String(ref s) => s.visit(visit), + Json::Object(ref object) => object.visit(visit), + } + } +} + +impl Valuable for Map { + fn as_value(&self) -> Value<'_> { + Value::Mappable(self) + } + + fn visit(&self, visit: &mut dyn Visit) { + for (k, v) in self.iter() { + visit.visit_entry(k.as_value(), v.as_value()); + } + } +} + +impl Mappable for Map { + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +#[cfg(test)] +mod test { + use crate::json; + use valuable::{Valuable, Value}; + + #[test] + fn test_json() { + let j = json!({"a": 100, "b": 1.0, "c": -1}); + let jv = j.as_value(); + + assert!(matches!(jv, Value::Mappable(_))); + + assert!(matches!(json!(100).as_value(), Value::I64(_))); + } +}