Skip to main content

db_http_core/
deserializer.rs

1use crate::error::Error;
2use crate::types::QueryResult;
3use serde::de::DeserializeOwned;
4
5pub fn deserialize_one<T: DeserializeOwned>(result: QueryResult) -> Result<T, Error> {
6    let row = result.rows.into_iter().next().ok_or(Error::NoRows)?;
7    serde_json::from_value(row).map_err(Error::Serialization)
8}
9
10pub fn deserialize_all<T: DeserializeOwned>(result: QueryResult) -> Result<Vec<T>, Error> {
11    result
12        .rows
13        .into_iter()
14        .map(|row| serde_json::from_value(row).map_err(Error::Serialization))
15        .collect()
16}
17
18#[cfg(test)]
19mod tests {
20    use super::*;
21    use serde::Deserialize;
22
23    fn make_result(rows: Vec<serde_json::Value>) -> QueryResult {
24        QueryResult {
25            columns: vec![],
26            rows,
27            affected_row_count: 0,
28        }
29    }
30
31    #[derive(Debug, Deserialize, PartialEq)]
32    struct User {
33        id: i64,
34        name: String,
35    }
36
37    #[derive(Debug, Deserialize, PartialEq)]
38    struct OptionalUser {
39        id: i64,
40        name: Option<String>,
41    }
42
43    #[derive(Debug, Deserialize, PartialEq)]
44    struct NestedMeta {
45        meta: serde_json::Value,
46    }
47
48    #[derive(Debug, Deserialize, PartialEq)]
49    struct MixedRow {
50        int_val: i64,
51        float_val: f64,
52        str_val: String,
53        bool_val: bool,
54        null_val: Option<String>,
55    }
56
57    #[derive(Debug, Deserialize, PartialEq)]
58    struct BoolStruct {
59        active: bool,
60    }
61
62    #[test]
63    fn deserialize_one_simple_struct() {
64        let result = make_result(vec![serde_json::json!({"id": 1, "name": "Alice"})]);
65        let user: User = deserialize_one(result).unwrap();
66        assert_eq!(user, User { id: 1, name: "Alice".to_string() });
67    }
68
69    #[test]
70    fn deserialize_all_multiple_rows() {
71        let result = make_result(vec![
72            serde_json::json!({"id": 1, "name": "Alice"}),
73            serde_json::json!({"id": 2, "name": "Bob"}),
74            serde_json::json!({"id": 3, "name": "Carol"}),
75        ]);
76        let users: Vec<User> = deserialize_all(result).unwrap();
77        assert_eq!(users.len(), 3);
78        assert_eq!(users[0].name, "Alice");
79        assert_eq!(users[1].name, "Bob");
80        assert_eq!(users[2].name, "Carol");
81    }
82
83    #[test]
84    fn deserialize_one_no_rows() {
85        let result = make_result(vec![]);
86        let err = deserialize_one::<User>(result).unwrap_err();
87        assert!(matches!(err, Error::NoRows));
88    }
89
90    #[test]
91    fn deserialize_all_empty() {
92        let result = make_result(vec![]);
93        let users: Vec<User> = deserialize_all(result).unwrap();
94        assert!(users.is_empty());
95    }
96
97    #[test]
98    fn deserialize_one_with_nulls() {
99        let result = make_result(vec![serde_json::json!({"id": 1, "name": null})]);
100        let user: OptionalUser = deserialize_one(result).unwrap();
101        assert_eq!(user, OptionalUser { id: 1, name: None });
102    }
103
104    #[test]
105    fn deserialize_one_type_mismatch() {
106        let result = make_result(vec![serde_json::json!({"id": "not_a_number", "name": "Alice"})]);
107        let err = deserialize_one::<User>(result).unwrap_err();
108        assert!(matches!(err, Error::Serialization(_)));
109    }
110
111    #[test]
112    fn deserialize_one_nested_json() {
113        let result = make_result(vec![serde_json::json!({"meta": {"key": "val"}})]);
114        let row: NestedMeta = deserialize_one(result).unwrap();
115        assert_eq!(row.meta, serde_json::json!({"key": "val"}));
116    }
117
118    #[test]
119    fn deserialize_all_mixed_types() {
120        let result = make_result(vec![serde_json::json!({
121            "int_val": 42,
122            "float_val": 3.14,
123            "str_val": "hello",
124            "bool_val": true,
125            "null_val": null
126        })]);
127        let rows: Vec<MixedRow> = deserialize_all(result).unwrap();
128        assert_eq!(rows.len(), 1);
129        assert_eq!(rows[0], MixedRow {
130            int_val: 42,
131            float_val: 3.14,
132            str_val: "hello".to_string(),
133            bool_val: true,
134            null_val: None,
135        });
136    }
137
138    #[test]
139    fn deserialize_one_extra_fields() {
140        let result = make_result(vec![serde_json::json!({"id": 1, "name": "Alice", "extra": "ignored"})]);
141        let user: User = deserialize_one(result).unwrap();
142        assert_eq!(user, User { id: 1, name: "Alice".to_string() });
143    }
144
145    #[test]
146    fn deserialize_one_bool_values() {
147        let result = make_result(vec![serde_json::json!({"active": true})]);
148        let row: BoolStruct = deserialize_one(result).unwrap();
149        assert_eq!(row, BoolStruct { active: true });
150
151        let result = make_result(vec![serde_json::json!({"active": false})]);
152        let row: BoolStruct = deserialize_one(result).unwrap();
153        assert_eq!(row, BoolStruct { active: false });
154    }
155}