db_http_core/
deserializer.rs1use 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}