value_ext/json/
json_value_ext.rs1use crate::AsType;
2use serde::de::DeserializeOwned;
3use serde::Serialize;
4use serde_json::{json, Map, Value};
5use std::collections::VecDeque;
6
7pub trait JsonValueExt {
65 fn x_new_object() -> Value;
66
67 fn x_contains<T: DeserializeOwned>(&self, name_or_pointer: &str) -> bool;
68
69 fn x_get<T: DeserializeOwned>(&self, name_or_pointer: &str) -> Result<T>;
72
73 fn x_get_as<'a, T: AsType<'a>>(&'a self, name_or_pointer: &str) -> Result<T>;
77
78 fn x_get_str(&self, name_or_pointer: &str) -> Result<&str> {
80 self.x_get_as(name_or_pointer)
81 }
82
83 fn x_get_i64(&self, name_or_pointer: &str) -> Result<i64> {
85 self.x_get_as(name_or_pointer)
86 }
87
88 fn x_get_f64(&self, name_or_pointer: &str) -> Result<f64> {
90 self.x_get_as(name_or_pointer)
91 }
92
93 fn x_get_bool(&self, name_or_pointer: &str) -> Result<bool> {
95 self.x_get_as(name_or_pointer)
96 }
97
98 fn x_take<T: DeserializeOwned>(&mut self, name_or_pointer: &str) -> Result<T>;
101
102 fn x_insert<T: Serialize>(&mut self, name_or_pointer: &str, value: T) -> Result<()>;
106
107 fn x_walk<F>(&mut self, callback: F) -> bool
115 where
116 F: FnMut(&mut Map<String, Value>, &str) -> bool;
117
118 fn x_pretty(&self) -> Result<String>;
120}
121
122impl JsonValueExt for Value {
123 fn x_new_object() -> Value {
124 Value::Object(Map::new())
125 }
126
127 fn x_contains<T: DeserializeOwned>(&self, name_or_pointer: &str) -> bool {
128 if name_or_pointer.starts_with('/') {
129 self.pointer(name_or_pointer).is_some()
130 } else {
131 self.get(name_or_pointer).is_some()
132 }
133 }
134
135 fn x_get<T: DeserializeOwned>(&self, name_or_pointer: &str) -> Result<T> {
136 let value = if name_or_pointer.starts_with('/') {
137 self.pointer(name_or_pointer)
138 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
139 } else {
140 self.get(name_or_pointer)
141 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
142 };
143
144 let value: T = serde_json::from_value(value.clone())
145 .map_err(JsonValueExtError::from)
147 .map_err(|err| match err {
149 JsonValueExtError::ValueNotOfType(not_of_type) => JsonValueExtError::PropertyValueNotOfType {
150 name: name_or_pointer.to_string(),
151 not_of_type,
152 },
153 other => other,
154 })?;
155
156 Ok(value)
157 }
158
159 fn x_get_as<'a, T: AsType<'a>>(&'a self, name_or_pointer: &str) -> Result<T> {
160 let value = if name_or_pointer.starts_with('/') {
161 self.pointer(name_or_pointer)
162 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
163 } else {
164 self.get(name_or_pointer)
165 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
166 };
167
168 T::from_value(value).map_err(|err| match err {
170 JsonValueExtError::ValueNotOfType(not_of_type) => JsonValueExtError::PropertyValueNotOfType {
171 name: name_or_pointer.to_string(),
172 not_of_type,
173 },
174 other => other,
175 })
176 }
177
178 fn x_take<T: DeserializeOwned>(&mut self, name_or_pointer: &str) -> Result<T> {
179 let value = if name_or_pointer.starts_with('/') {
180 self.pointer_mut(name_or_pointer)
181 .map(Value::take)
182 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
183 } else {
184 self.get_mut(name_or_pointer)
185 .map(Value::take)
186 .ok_or_else(|| JsonValueExtError::PropertyNotFound(name_or_pointer.to_string()))?
187 };
188
189 let value: T = serde_json::from_value(value)?;
190 Ok(value)
191 }
192
193 fn x_insert<T: Serialize>(&mut self, name_or_pointer: &str, value: T) -> Result<()> {
194 let new_value = serde_json::to_value(value)?;
195
196 if !name_or_pointer.starts_with('/') {
197 match self {
198 Value::Object(map) => {
199 map.insert(name_or_pointer.to_string(), new_value);
200 Ok(())
201 }
202 _ => Err(JsonValueExtError::custom("Value is not an Object; cannot x_insert")),
203 }
204 } else {
205 let parts: Vec<&str> = name_or_pointer.split('/').skip(1).collect();
206 let mut current = self;
207
208 for &part in &parts[..parts.len() - 1] {
210 match current {
211 Value::Object(map) => {
212 current = map.entry(part).or_insert_with(|| json!({}));
213 }
214 _ => return Err(JsonValueExtError::custom("Path does not point to an Object")),
215 }
216 }
217
218 if let Some(&last_part) = parts.last() {
220 match current {
221 Value::Object(map) => {
222 map.insert(last_part.to_string(), new_value);
223 Ok(())
224 }
225 _ => Err(JsonValueExtError::custom("Path does not point to an Object")),
226 }
227 } else {
228 Err(JsonValueExtError::custom("Invalid path"))
229 }
230 }
231 }
232
233 fn x_pretty(&self) -> Result<String> {
234 let content = serde_json::to_string_pretty(self)?;
235 Ok(content)
236 }
237
238 fn x_walk<F>(&mut self, mut callback: F) -> bool
247 where
248 F: FnMut(&mut Map<String, Value>, &str) -> bool,
249 {
250 let mut queue = VecDeque::new();
251 queue.push_back(self);
252
253 while let Some(current) = queue.pop_front() {
254 if let Value::Object(map) = current {
255 for key in map.keys().cloned().collect::<Vec<_>>() {
257 let res = callback(map, &key);
258 if !res {
259 return false;
260 }
261 }
262
263 for value in map.values_mut() {
265 if value.is_object() || value.is_array() {
266 queue.push_back(value);
267 }
268 }
269 } else if let Value::Array(arr) = current {
270 for value in arr.iter_mut() {
272 if value.is_object() || value.is_array() {
273 queue.push_back(value);
274 }
275 }
276 }
277 }
278 true
279 }
280}
281
282type Result<T> = core::result::Result<T, JsonValueExtError>;
284
285#[derive(Debug, derive_more::From)]
286pub enum JsonValueExtError {
287 Custom(String),
288
289 PropertyNotFound(String),
290
291 PropertyValueNotOfType {
292 name: String,
293 not_of_type: &'static str,
294 },
295
296 ValueNotOfType(&'static str),
298
299 #[from]
300 SerdeJson(serde_json::Error),
301}
302
303impl JsonValueExtError {
304 pub(crate) fn custom(val: impl std::fmt::Display) -> Self {
305 Self::Custom(val.to_string())
306 }
307}
308
309impl core::fmt::Display for JsonValueExtError {
312 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
313 write!(fmt, "{self:?}")
314 }
315}
316
317impl std::error::Error for JsonValueExtError {}
318
319