serde_json_diagnostics/
de.rs

1//! Deserialization module with public API functions.
2//!
3//! This module provides drop-in replacements for serde_json's convenience
4//! functions that return enhanced errors with path tracking.
5
6use crate::error::{ErrorDiagnostic, Result};
7
8/// Deserialize an instance of type `T` from a string of JSON text.
9///
10/// This function provides the same API as `serde_json::from_str` but returns
11/// enhanced errors with path tracking. Returns `ErrorDiagnostic` if the JSON
12/// is invalid or if the data does not match `T`'s structure. The error
13/// includes the JSON path to the error location (primary indicator) and
14/// line/column numbers from serde_json (supplemental information that may be
15/// inaccurate).
16///
17/// # Example
18///
19/// ```rust
20/// use serde::Deserialize;
21/// use serde_json_diagnostics::from_str;
22///
23/// #[derive(Deserialize)]
24/// struct User {
25///     name: String,
26///     age: u32,
27/// }
28///
29/// let json = r#"{"name": "Alice", "age": 30}"#;
30/// let user: User = from_str(json)?;
31/// # Ok::<(), serde_json_diagnostics::ErrorDiagnostic>(())
32/// ```
33///
34/// # Note on Path Tracking
35///
36/// Path tracking implementation is pending completion in Phase 4. Currently,
37/// this function uses serde_json internally without path information. The API
38/// signature is correct and will provide enhanced errors once path tracking
39/// is implemented.
40pub fn from_str<'a, T>(s: &'a str) -> Result<T>
41where
42    T: serde::Deserialize<'a>,
43{
44    serde_json::from_str(s).map_err(ErrorDiagnostic::new)
45}
46
47/// Deserialize an instance of type `T` from bytes of JSON text.
48///
49/// This function provides the same API as `serde_json::from_slice` but returns
50/// enhanced errors with path tracking.
51///
52/// # Example
53///
54/// ```rust
55/// use serde::Deserialize;
56/// use serde_json_diagnostics::from_slice;
57///
58/// #[derive(Deserialize)]
59/// struct Config {
60///     debug: bool,
61/// }
62///
63/// let bytes = br#"{"debug": true}"#;
64/// let config: Config = from_slice(bytes)?;
65/// # Ok::<(), serde_json_diagnostics::ErrorDiagnostic>(())
66/// ```
67///
68/// # Note on Path Tracking
69///
70/// Path tracking implementation is pending completion in Phase 4. Currently,
71/// this function uses serde_json internally without path information.
72pub fn from_slice<'a, T>(bytes: &'a [u8]) -> Result<T>
73where
74    T: serde::Deserialize<'a>,
75{
76    serde_json::from_slice(bytes).map_err(ErrorDiagnostic::new)
77}
78
79/// Deserialize an instance of type `T` from an IO stream of JSON.
80///
81/// This function provides the same API as `serde_json::from_reader` but returns
82/// enhanced errors with path tracking.
83///
84/// # Example
85///
86/// ```rust
87/// use serde::Deserialize;
88/// use serde_json_diagnostics::from_reader;
89/// use std::io::Cursor;
90///
91/// #[derive(Deserialize)]
92/// struct Data {
93///     value: i32,
94/// }
95///
96/// let json = r#"{"value": 42}"#;
97/// let reader = Cursor::new(json);
98/// let data: Data = from_reader(reader)?;
99/// # Ok::<(), serde_json_diagnostics::ErrorDiagnostic>(())
100/// ```
101///
102/// # Note on Path Tracking
103///
104/// Path tracking implementation is pending completion in Phase 4. Currently,
105/// this function uses serde_json internally without path information.
106pub fn from_reader<R, T>(reader: R) -> Result<T>
107where
108    R: std::io::Read,
109    T: serde::de::DeserializeOwned,
110{
111    serde_json::from_reader(reader).map_err(ErrorDiagnostic::new)
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117    use serde::Deserialize;
118
119    #[test]
120    fn from_str_api_compiles() {
121        let json = r#"{"name": "test"}"#;
122        let result: Result<serde_json::Value> = from_str(json);
123        assert!(result.is_ok());
124
125        let value = result.unwrap();
126        assert_eq!(value["name"], "test");
127    }
128
129    #[test]
130    fn from_str_with_struct() {
131        #[derive(Deserialize, Debug, PartialEq)]
132        struct User {
133            name: String,
134            age: u32,
135        }
136
137        let json = r#"{"name": "Alice", "age": 30}"#;
138        let result: Result<User> = from_str(json);
139        assert!(result.is_ok());
140
141        let user = result.unwrap();
142        assert_eq!(user.name, "Alice");
143        assert_eq!(user.age, 30);
144    }
145
146    #[test]
147    fn from_str_error_returns_error_diagnostic() {
148        let json = r#"{"name": "Bob", "age": "not_a_number"}"#;
149        let result: Result<serde_json::Value> = from_str(json);
150
151        assert!(result.is_ok());
152    }
153
154    #[test]
155    fn from_slice_api_compiles() {
156        let bytes = br#"{"key": "value"}"#;
157        let result: Result<serde_json::Value> = from_slice(bytes);
158        assert!(result.is_ok());
159
160        let value = result.unwrap();
161        assert_eq!(value["key"], "value");
162    }
163
164    #[test]
165    fn from_slice_with_struct() {
166        #[derive(Deserialize, Debug, PartialEq)]
167        struct Config {
168            enabled: bool,
169        }
170
171        let bytes = br#"{"enabled": true}"#;
172        let result: Result<Config> = from_slice(bytes);
173        assert!(result.is_ok());
174
175        let config = result.unwrap();
176        assert!(config.enabled);
177    }
178
179    #[test]
180    fn from_reader_api_compiles() {
181        use std::io::Cursor;
182
183        let json = r#"{"test": 123}"#;
184        let reader = Cursor::new(json);
185        let result: Result<serde_json::Value> = from_reader(reader);
186        assert!(result.is_ok());
187
188        let value = result.unwrap();
189        assert_eq!(value["test"], 123);
190    }
191
192    #[test]
193    fn from_reader_with_struct() {
194        use std::io::Cursor;
195
196        #[derive(Deserialize, Debug, PartialEq)]
197        struct Point {
198            x: f64,
199            y: f64,
200        }
201
202        let json = r#"{"x": 1.5, "y": 2.5}"#;
203        let reader = Cursor::new(json);
204        let result: Result<Point> = from_reader(reader);
205        assert!(result.is_ok());
206
207        let point = result.unwrap();
208        assert_eq!(point.x, 1.5);
209        assert_eq!(point.y, 2.5);
210    }
211}