1use serde::de::{DeserializeOwned, Error};
2
3#[derive(Debug, serde::Serialize, serde::Deserialize)]
9#[serde(untagged)]
10pub enum JsonResult<T, E> {
11 Ok(T),
13 Err(E),
15}
16
17impl<T, E> From<JsonResult<T, E>> for serde_json::Value
18where
19 T: serde::Serialize,
20 E: serde::Serialize,
21{
22 fn from(res: JsonResult<T, E>) -> Self {
36 match res {
37 JsonResult::Ok(v) => serde_json::json!(v),
38 JsonResult::Err(e) => serde_json::json!(e),
39 }
40 }
41}
42
43impl<T, E> TryFrom<serde_json::Value> for JsonResult<T, E>
44where
45 T: DeserializeOwned,
46 E: DeserializeOwned,
47{
48 type Error = serde_json::Error;
49
50 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
72 let t_res = serde_json::from_value::<T>(value.clone());
73 let e_res = serde_json::from_value::<E>(value);
74
75 match (t_res, e_res) {
76 (Ok(v), _) => Ok(JsonResult::Ok(v)),
77 (_, Ok(e)) => Ok(JsonResult::Err(e)),
78 (Err(t_err), Err(e_err)) => {
79 let t_name = std::any::type_name::<T>();
80 let e_name = std::any::type_name::<E>();
81 let message = format!(
82 "Failed to parse as {}: {}\nFailed to parse as {}: {}",
83 t_name, t_err, e_name, e_err
84 );
85 Err(serde_json::Error::custom(message))
86 }
87 }
88 }
89}
90
91impl<T, E> From<Result<T, E>> for JsonResult<T, E> {
92 fn from(r: Result<T, E>) -> Self {
93 match r {
94 Ok(v) => JsonResult::Ok(v),
95 Err(e) => JsonResult::Err(e),
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use crate::r#enum::JsonResult;
103 use serde::{Deserialize, Serialize};
104
105 #[derive(Debug, Serialize, Deserialize, PartialEq)]
106 struct GoodT {
107 x: u32,
108 }
109
110 #[derive(Debug, Serialize, Deserialize, PartialEq)]
111 struct BadE {
112 msg: String,
113 }
114
115 #[test]
116 fn test_good_case_ok_t() {
117 let original: JsonResult<GoodT, BadE> = JsonResult::Ok(GoodT { x: 123 });
118
119 let json = serde_json::to_value(&original).unwrap();
120 let parsed = JsonResult::<GoodT, BadE>::try_from(json).unwrap();
121
122 match parsed {
123 JsonResult::Ok(v) => assert_eq!(v, GoodT { x: 123 }),
124 _ => panic!("Expected Ok(T)"),
125 }
126 }
127
128 #[test]
129 fn test_good_case_err_e() {
130 let original: JsonResult<GoodT, BadE> = JsonResult::Err(BadE { msg: "fail".into() });
131
132 let json = serde_json::to_value(&original).unwrap();
133 let parsed = JsonResult::<GoodT, BadE>::try_from(json).unwrap();
134
135 match parsed {
136 JsonResult::Err(e) => assert_eq!(e, BadE { msg: "fail".into() }),
137 _ => panic!("Expected Err(E)"),
138 }
139 }
140
141 #[test]
142 fn test_bad_case_neither_matches() {
143 let json = serde_json::json!({ "something": 9999 });
144
145 let result = JsonResult::<GoodT, BadE>::try_from(json);
146
147 assert!(result.is_err());
148
149 let msg = result.unwrap_err().to_string();
150 assert!(msg.contains("GoodT"));
151 assert!(msg.contains("BadE"));
152 assert!(msg.contains("Failed to parse"));
153 }
154
155 #[test]
156 fn test_round_trip_t() {
157 let original: JsonResult<GoodT, BadE> = JsonResult::Ok(GoodT { x: 42 });
158
159 let json: serde_json::Value = original.into();
160 let parsed = JsonResult::<GoodT, BadE>::try_from(json).unwrap();
161
162 match parsed {
163 JsonResult::Ok(v) => assert_eq!(v.x, 42),
164 _ => panic!("Round trip for T failed"),
165 }
166 }
167
168 #[test]
169 fn test_round_trip_e() {
170 let original: JsonResult<GoodT, BadE> = JsonResult::Err(BadE { msg: "boom".into() });
171
172 let json: serde_json::Value = original.into();
173 let parsed = JsonResult::<GoodT, BadE>::try_from(json).unwrap();
174
175 match parsed {
176 JsonResult::Err(v) => assert_eq!(v.msg, "boom"),
177 _ => panic!("Round trip for E failed"),
178 }
179 }
180
181 #[test]
182 fn test_empty_object() {
183 let json = serde_json::json!({});
184
185 let result = JsonResult::<GoodT, BadE>::try_from(json);
187 assert!(result.is_err());
188 }
189
190 #[test]
191 fn test_null_value() {
192 let json = serde_json::json!(null);
193
194 let result = JsonResult::<GoodT, BadE>::try_from(json);
195 assert!(result.is_err());
196 }
197
198 #[test]
199 fn test_primitive_value_matches_t() {
200 #[derive(Debug, Serialize, Deserialize, PartialEq)]
202 struct NumberT(u32);
203
204 #[derive(Debug, Serialize, Deserialize, PartialEq)]
205 struct StringE(String);
206
207 let json = serde_json::json!(123u32);
208 let parsed = JsonResult::<NumberT, StringE>::try_from(json).unwrap();
209
210 match parsed {
211 JsonResult::Ok(NumberT(n)) => assert_eq!(n, 123),
212 _ => panic!("Expected Ok(NumberT)"),
213 }
214 }
215
216 #[test]
217 fn test_primitive_value_matches_e() {
218 #[derive(Debug, Serialize, Deserialize, PartialEq)]
219 struct NumberT(u32);
220
221 #[derive(Debug, Serialize, Deserialize, PartialEq)]
222 struct StringE(String);
223
224 let json = serde_json::json!("error message");
225 let parsed = JsonResult::<NumberT, StringE>::try_from(json).unwrap();
226
227 match parsed {
228 JsonResult::Err(StringE(s)) => assert_eq!(s, "error message"),
229 _ => panic!("Expected Err(StringE)"),
230 }
231 }
232
233 #[test]
234 fn test_ambiguous_value() {
235 #[derive(Debug, Serialize, Deserialize, PartialEq)]
237 struct Ambiguous {
238 value: u32,
239 }
240
241 let json = serde_json::json!({ "value": 55 });
242
243 let parsed = JsonResult::<Ambiguous, Ambiguous>::try_from(json).unwrap();
245
246 match parsed {
247 JsonResult::Ok(Ambiguous { value }) => assert_eq!(value, 55),
248 _ => panic!("Expected Ok variant for ambiguous type"),
249 }
250 }
251
252 #[test]
253 fn test_deeply_nested_json() {
254 #[derive(Debug, Serialize, Deserialize, PartialEq)]
255 struct NestedT {
256 nested: Option<Box<NestedT>>,
257 val: u32,
258 }
259
260 #[derive(Debug, Serialize, Deserialize, PartialEq)]
261 struct NestedE {
262 error: String,
263 }
264
265 let json = serde_json::json!({
266 "nested": {
267 "nested": null,
268 "val": 10
269 },
270 "val": 5
271 });
272
273 let parsed = JsonResult::<NestedT, NestedE>::try_from(json).unwrap();
274
275 match parsed {
276 JsonResult::Ok(n) => {
277 assert_eq!(n.val, 5);
278 assert!(n.nested.is_some());
279 let inner = n.nested.unwrap();
280 assert_eq!(inner.val, 10);
281 assert!(inner.nested.is_none());
282 }
283 _ => panic!("Expected Ok with nested structure"),
284 }
285 }
286
287 #[test]
288 fn test_invalid_json_structure() {
289 let json = serde_json::json!([1, 2, 3]);
291
292 let result = JsonResult::<GoodT, BadE>::try_from(json);
293 assert!(result.is_err());
294 }
295
296 #[test]
297 fn test_error_message_contains_correct_type_names() {
298 #[derive(Debug, Serialize, Deserialize)]
300 struct ComplexType {
301 field: String,
302 }
303
304 let json = serde_json::json!("just a string");
305
306 let result = JsonResult::<ComplexType, ComplexType>::try_from(json);
307 assert!(result.is_err());
308
309 let err_str = result.unwrap_err().to_string();
310 assert!(err_str.contains("ComplexType"));
311 assert!(err_str.contains("Failed to parse"));
312 }
313
314 #[derive(Debug, Serialize, Deserialize, PartialEq)]
315 struct OKData {
316 value: i32,
317 }
318
319 #[derive(Debug, Serialize, Deserialize, PartialEq)]
320 struct ErrData {
321 message: String,
322 }
323
324 #[test]
325 fn test_from_result_ok() {
326 let r: Result<OKData, ErrData> = Ok(OKData { value: 123 });
327
328 let jr: JsonResult<OKData, ErrData> = JsonResult::from(r);
329
330 match jr {
331 JsonResult::Ok(ok) => assert_eq!(ok.value, 123),
332 _ => panic!("Expected JsonResult::Ok"),
333 }
334 }
335
336 #[test]
337 fn test_from_result_err() {
338 let r: Result<OKData, ErrData> = Err(ErrData {
339 message: "boom".into(),
340 });
341
342 let jr: JsonResult<OKData, ErrData> = JsonResult::from(r);
343
344 match jr {
345 JsonResult::Err(e) => assert_eq!(e.message, "boom"),
346 _ => panic!("Expected JsonResult::Err"),
347 }
348 }
349
350 #[test]
351 fn test_from_result_type_check() {
352 let res: Result<i32, &str> = Ok(10);
354 let jr: JsonResult<i32, &str> = res.into();
355
356 assert!(matches!(jr, JsonResult::Ok(10)));
357 }
358
359 #[test]
360 fn test_from_result_error_type_check() {
361 let res: Result<i32, &str> = Err("wrong");
362 let jr: JsonResult<i32, &str> = res.into();
363
364 assert!(matches!(jr, JsonResult::Err("wrong")));
365 }
366}