Skip to main content

rh_foundation/
json.rs

1//! JSON utility functions.
2//!
3//! This module provides convenience functions for working with JSON.
4
5use crate::error::Result;
6use serde::{Deserialize, Serialize};
7
8/// Parse a JSON string into a typed value.
9pub fn parse<T>(json: &str) -> Result<T>
10where
11    T: for<'de> Deserialize<'de>,
12{
13    serde_json::from_str(json).map_err(Into::into)
14}
15
16/// Serialize a value to a JSON string.
17pub fn stringify<T>(value: &T, pretty: bool) -> Result<String>
18where
19    T: Serialize,
20{
21    if pretty {
22        serde_json::to_string_pretty(value).map_err(Into::into)
23    } else {
24        serde_json::to_string(value).map_err(Into::into)
25    }
26}
27
28/// Parse a JSON value from bytes.
29pub fn from_bytes<T>(bytes: &[u8]) -> Result<T>
30where
31    T: for<'de> Deserialize<'de>,
32{
33    serde_json::from_slice(bytes).map_err(Into::into)
34}
35
36/// Serialize a value to JSON bytes.
37pub fn to_bytes<T>(value: &T, pretty: bool) -> Result<Vec<u8>>
38where
39    T: Serialize,
40{
41    if pretty {
42        serde_json::to_vec_pretty(value).map_err(Into::into)
43    } else {
44        serde_json::to_vec(value).map_err(Into::into)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use serde::{Deserialize, Serialize};
52
53    #[derive(Debug, Serialize, Deserialize, PartialEq)]
54    struct TestData {
55        name: String,
56        count: i32,
57    }
58
59    #[test]
60    fn test_parse_and_stringify() {
61        let data = TestData {
62            name: "test".to_string(),
63            count: 42,
64        };
65
66        let json = stringify(&data, false).unwrap();
67        let parsed: TestData = parse(&json).unwrap();
68
69        assert_eq!(data, parsed);
70    }
71
72    #[test]
73    fn test_bytes_roundtrip() {
74        let data = TestData {
75            name: "test".to_string(),
76            count: 42,
77        };
78
79        let bytes = to_bytes(&data, false).unwrap();
80        let parsed: TestData = from_bytes(&bytes).unwrap();
81
82        assert_eq!(data, parsed);
83    }
84
85    #[test]
86    fn test_pretty_print() {
87        let data = TestData {
88            name: "test".to_string(),
89            count: 42,
90        };
91
92        let pretty = stringify(&data, true).unwrap();
93        assert!(pretty.contains('\n'));
94        assert!(pretty.contains("  "));
95    }
96}