1use serde::{Deserialize, Serialize};
11use serde_json::Value as JsonValue;
12use std::hash::{Hash, Hasher};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum JsonError {
17 InvalidJson(String),
18 InvalidPath(String),
19 TypeMismatch { expected: String, actual: String },
20}
21
22impl std::fmt::Display for JsonError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 JsonError::InvalidJson(msg) => write!(f, "Invalid JSON: {}", msg),
26 JsonError::InvalidPath(path) => write!(f, "Invalid JSON path: {}", path),
27 JsonError::TypeMismatch { expected, actual } => {
28 write!(f, "Type mismatch: expected {}, got {}", expected, actual)
29 }
30 }
31 }
32}
33
34impl std::error::Error for JsonError {}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct Json {
44 text: String,
46 #[serde(skip)]
48 cached_value: Option<JsonValue>,
49}
50
51#[derive(Debug, Clone)]
63pub struct JsonB {
64 value: JsonValue,
65}
66
67impl Serialize for JsonB {
68 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
69 serializer.serialize_str(&self.value.to_string())
70 }
71}
72
73impl<'de> Deserialize<'de> for JsonB {
74 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
75 let text = String::deserialize(deserializer)?;
76 serde_json::from_str(&text)
77 .map(Self::from_value)
78 .map_err(serde::de::Error::custom)
79 }
80}
81
82impl Json {
83 pub fn parse(text: &str) -> Result<Self, JsonError> {
85 let value: JsonValue =
87 serde_json::from_str(text).map_err(|e| JsonError::InvalidJson(e.to_string()))?;
88
89 Ok(Self {
90 text: text.to_string(),
91 cached_value: Some(value),
92 })
93 }
94
95 pub fn from_value(value: JsonValue) -> Self {
97 let text = value.to_string();
98 Self {
99 text,
100 cached_value: Some(value),
101 }
102 }
103
104 pub fn as_str(&self) -> &str {
106 &self.text
107 }
108
109 pub fn to_value(&self) -> Result<JsonValue, JsonError> {
111 if let Some(ref value) = self.cached_value {
112 return Ok(value.clone());
113 }
114
115 serde_json::from_str(&self.text).map_err(|e| JsonError::InvalidJson(e.to_string()))
116 }
117
118 pub fn get_path(&self, path: &str) -> Result<Option<JsonValue>, JsonError> {
121 let value = self.to_value()?;
122 Ok(get_json_path(&value, path))
123 }
124
125 pub fn to_jsonb(&self) -> Result<JsonB, JsonError> {
127 let value = self.to_value()?;
128 Ok(JsonB::from_value(value))
129 }
130
131 pub fn extract(&self, path: &str) -> Result<Json, JsonError> {
133 let json_value = self.get_path(path)?;
134 Ok(Json::from_value(json_value.unwrap_or(JsonValue::Null)))
135 }
136
137 pub fn estimated_size(&self) -> usize {
139 std::mem::size_of::<Self>() + self.text.capacity()
140 }
141}
142
143impl PartialEq for Json {
144 fn eq(&self, other: &Self) -> bool {
145 match (self.to_value(), other.to_value()) {
147 (Ok(a), Ok(b)) => a == b,
148 _ => false,
149 }
150 }
151}
152
153impl Eq for Json {}
154
155impl Hash for Json {
156 fn hash<H: Hasher>(&self, state: &mut H) {
157 if let Ok(value) = self.to_value() {
159 hash_json_value(&value, state);
160 }
161 }
162}
163
164impl JsonB {
167 pub fn parse(text: &str) -> Result<Self, JsonError> {
169 let value: JsonValue =
170 serde_json::from_str(text).map_err(|e| JsonError::InvalidJson(e.to_string()))?;
171
172 Ok(Self::from_value(value))
173 }
174
175 pub fn from_value(value: JsonValue) -> Self {
177 let normalized = normalize_json(value);
179
180 Self { value: normalized }
181 }
182
183 pub fn as_value(&self) -> &JsonValue {
185 &self.value
186 }
187
188 pub fn to_json_string(&self) -> String {
190 self.value.to_string()
191 }
192
193 pub fn get_path(&self, path: &str) -> Option<&JsonValue> {
195 get_json_path_ref(&self.value, path)
196 }
197
198 pub fn to_json(&self) -> Json {
200 Json::from_value(self.value.clone())
201 }
202
203 pub fn contains_key(&self, key: &str) -> bool {
205 matches!(self.value, JsonValue::Object(ref map) if map.contains_key(key))
206 }
207
208 pub fn key_count(&self) -> usize {
210 match self.value {
211 JsonValue::Object(ref map) => map.len(),
212 _ => 0,
213 }
214 }
215
216 pub fn array_len(&self) -> Option<usize> {
218 match self.value {
219 JsonValue::Array(ref arr) => Some(arr.len()),
220 _ => None,
221 }
222 }
223
224 pub fn extract(&self, path: &str) -> JsonB {
226 let json_value = self.get_path(path).cloned().unwrap_or(JsonValue::Null);
227 JsonB::from_value(json_value)
228 }
229
230 pub fn estimated_size(&self) -> usize {
232 std::mem::size_of::<Self>() + estimate_json_size(&self.value)
233 }
234}
235
236impl PartialEq for JsonB {
237 fn eq(&self, other: &Self) -> bool {
238 self.value == other.value
239 }
240}
241
242impl Eq for JsonB {}
243
244impl Hash for JsonB {
245 fn hash<H: Hasher>(&self, state: &mut H) {
246 hash_json_value(&self.value, state);
247 }
248}
249
250impl Ord for JsonB {
251 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
252 compare_json_values(&self.value, &other.value)
254 }
255}
256
257impl PartialOrd for JsonB {
258 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
259 Some(self.cmp(other))
260 }
261}
262
263fn normalize_json(value: JsonValue) -> JsonValue {
267 match value {
268 JsonValue::Object(map) => {
269 let mut entries: Vec<_> = map.into_iter().collect();
271 entries.sort_by(|a, b| a.0.cmp(&b.0));
272 let normalized: serde_json::Map<String, JsonValue> = entries
273 .into_iter()
274 .map(|(k, v)| (k, normalize_json(v)))
275 .collect();
276 JsonValue::Object(normalized)
277 }
278 JsonValue::Array(arr) => JsonValue::Array(arr.into_iter().map(normalize_json).collect()),
279 other => other,
281 }
282}
283
284fn get_json_path(value: &JsonValue, path: &str) -> Option<JsonValue> {
286 let parts: Vec<&str> = path.split('.').collect();
287 let mut current = value;
288
289 for part in parts {
290 if let Some(idx_start) = part.find('[') {
292 let key = &part[..idx_start];
293 let idx_end = part.find(']').unwrap_or(part.len());
294 let idx: usize = part[idx_start + 1..idx_end].parse().ok()?;
295
296 if !key.is_empty() {
297 current = current.get(key)?;
298 }
299 current = current.get(idx)?;
300 } else {
301 current = current.get(part)?;
302 }
303 }
304
305 Some(current.clone())
306}
307
308fn get_json_path_ref<'a>(value: &'a JsonValue, path: &str) -> Option<&'a JsonValue> {
310 let parts: Vec<&str> = path.split('.').collect();
311 let mut current = value;
312
313 for part in parts {
314 if let Some(idx_start) = part.find('[') {
315 let key = &part[..idx_start];
316 let idx_end = part.find(']').unwrap_or(part.len());
317 let idx: usize = part[idx_start + 1..idx_end].parse().ok()?;
318
319 if !key.is_empty() {
320 current = current.get(key)?;
321 }
322 current = current.get(idx)?;
323 } else {
324 current = current.get(part)?;
325 }
326 }
327
328 Some(current)
329}
330
331fn hash_json_value<H: Hasher>(value: &JsonValue, state: &mut H) {
333 match value {
334 JsonValue::Null => 0u8.hash(state),
335 JsonValue::Bool(b) => {
336 1u8.hash(state);
337 b.hash(state);
338 }
339 JsonValue::Number(n) => {
340 2u8.hash(state);
341 n.to_string().hash(state);
342 }
343 JsonValue::String(s) => {
344 3u8.hash(state);
345 s.hash(state);
346 }
347 JsonValue::Array(arr) => {
348 4u8.hash(state);
349 for item in arr {
350 hash_json_value(item, state);
351 }
352 }
353 JsonValue::Object(map) => {
354 5u8.hash(state);
355 for (k, v) in map {
356 k.hash(state);
357 hash_json_value(v, state);
358 }
359 }
360 }
361}
362
363fn compare_json_values(a: &JsonValue, b: &JsonValue) -> std::cmp::Ordering {
365 use std::cmp::Ordering;
366
367 let type_priority = |v: &JsonValue| match v {
369 JsonValue::Null => 0,
370 JsonValue::Bool(_) => 1,
371 JsonValue::Number(_) => 2,
372 JsonValue::String(_) => 3,
373 JsonValue::Array(_) => 4,
374 JsonValue::Object(_) => 5,
375 };
376
377 let priority_a = type_priority(a);
378 let priority_b = type_priority(b);
379
380 match priority_a.cmp(&priority_b) {
381 Ordering::Equal => match (a, b) {
382 (JsonValue::Null, JsonValue::Null) => Ordering::Equal,
383 (JsonValue::Bool(a), JsonValue::Bool(b)) => a.cmp(b),
384 (JsonValue::Number(a), JsonValue::Number(b)) => {
385 if let (Some(a_i), Some(b_i)) = (a.as_i64(), b.as_i64()) {
387 a_i.cmp(&b_i)
388 } else if let (Some(a_f), Some(b_f)) = (a.as_f64(), b.as_f64()) {
389 a_f.partial_cmp(&b_f).unwrap_or(Ordering::Equal)
390 } else {
391 a.to_string().cmp(&b.to_string())
392 }
393 }
394 (JsonValue::String(a), JsonValue::String(b)) => a.cmp(b),
395 (JsonValue::Array(a), JsonValue::Array(b)) => a
396 .iter()
397 .zip(b.iter())
398 .map(|(x, y)| compare_json_values(x, y))
399 .find(|&ord| ord != Ordering::Equal)
400 .unwrap_or_else(|| a.len().cmp(&b.len())),
401 (JsonValue::Object(a), JsonValue::Object(b)) => {
402 let a_keys: Vec<_> = a.keys().collect();
403 let b_keys: Vec<_> = b.keys().collect();
404
405 match a_keys.cmp(&b_keys) {
406 Ordering::Equal => a_keys
407 .iter()
408 .map(|k| compare_json_values(&a[*k], &b[*k]))
409 .find(|&ord| ord != Ordering::Equal)
410 .unwrap_or(Ordering::Equal),
411 other => other,
412 }
413 }
414 _ => Ordering::Equal, },
416 other => other,
417 }
418}
419
420fn estimate_json_size(value: &JsonValue) -> usize {
422 match value {
423 JsonValue::Null => 0,
424 JsonValue::Bool(_) => 1,
425 JsonValue::Number(n) => n.to_string().len(),
426 JsonValue::String(s) => s.len(),
427 JsonValue::Array(arr) => {
428 arr.iter().map(estimate_json_size).sum::<usize>()
429 + arr.len() * std::mem::size_of::<JsonValue>()
430 }
431 JsonValue::Object(map) => {
432 map.iter()
433 .map(|(k, v)| k.len() + estimate_json_size(v))
434 .sum::<usize>()
435 + map.len() * std::mem::size_of::<(String, JsonValue)>()
436 }
437 }
438}
439
440#[cfg(test)]
441mod tests {
442 use super::*;
443
444 #[test]
445 fn test_json_from_str() {
446 let json = Json::parse(r#"{"name": "test", "value": 123}"#).unwrap();
447 assert!(json.get_path("name").unwrap().is_some());
448 assert!(json.get_path("value").unwrap().is_some());
449 }
450
451 #[test]
452 fn test_jsonb_from_str() {
453 let jsonb = JsonB::parse(r#"{"name": "test", "value": 123}"#).unwrap();
454 assert!(jsonb.contains_key("name"));
455 assert!(jsonb.contains_key("value"));
456 assert_eq!(jsonb.key_count(), 2);
457 }
458
459 #[test]
460 fn test_json_path() {
461 let json = Json::parse(r#"{"items": [{"name": "a"}, {"name": "b"}]}"#).unwrap();
462 let value = json.get_path("items[0].name").unwrap();
463 assert!(value.is_some());
464 }
465
466 #[test]
467 fn test_json_to_jsonb() {
468 let json = Json::parse(r#"{"test": 123}"#).unwrap();
469 let jsonb = json.to_jsonb().unwrap();
470 assert!(jsonb.contains_key("test"));
471 }
472
473 #[test]
474 fn test_jsonb_comparison() {
475 let a = JsonB::parse("1").unwrap();
476 let b = JsonB::parse("2").unwrap();
477 assert!(a < b);
478 }
479
480 #[test]
481 fn test_jsonb_equality() {
482 let a = JsonB::parse(r#"{"b": 1, "a": 2}"#).unwrap();
483 let b = JsonB::parse(r#"{"a": 2, "b": 1}"#).unwrap();
484 assert_eq!(a, b);
486 }
487}