1use std::error::Error;
3use std::fmt::{Debug, Display};
4use log::error;
5use serde::{Serialize,Deserialize};
6
7#[derive(Debug, Serialize, Deserialize)]
9pub struct ApiResp {
10 success: bool,
12 code: i32,
14 message: String,
16 data: Option<serde_json::Value>,
18}
19
20impl ApiResp {
21 pub fn is_success(&self) -> bool { self.success }
22
23 pub fn get_code(&self) -> i32 { self.code }
24
25 pub fn get_message(&self) -> &String { &self.message }
26
27 pub fn get_data(&self) -> &Option<serde_json::Value> { &self.data }
28
29 pub fn to_json(&self) -> String {
30 match serde_json::to_string(&self) {
31 Ok(json) => json,
32 Err(e) => {
33 error!("序列化json字符串时出错!{}", e);
34 let err_resp = ApiResp::error(-1, "处理响应结果时出错!".to_string());
35 serde_json::to_string(&err_resp).unwrap()
36 }
37 }
38 }
39}
40
41impl ApiResp {
42 pub fn success(data: serde_json::Value) -> ApiResp {
59 ApiResp {
60 success: true,
61 code: 0,
62 message: "".to_string(),
63 data: Some(data),
64 }
65 }
66
67 pub fn suc() -> ApiResp {
78 ApiResp {
79 success: true,
80 code: 0,
81 message: "".to_string(),
82 data: None,
83 }
84 }
85
86
87 pub fn error(code: i32, message: String) -> ApiResp {
103 ApiResp {
104 success: false,
105 code,
106 message,
107 data: None,
108 }
109 }
110}
111
112pub type DaoResult = Result<ApiResp, Box<dyn Error>>;
114
115pub trait TransformResult {
117 fn to_json_str<T>(self, err_log: T) -> String where T: Debug + Display;
150}
151
152impl TransformResult for DaoResult {
153 fn to_json_str<T>(self, err_log: T) -> String where T: Debug + Display {
154 let ret: ApiResp = match self {
155 Ok(r) => r,
156 Err(e) => {
157 error!("{} {:?}", err_log, e);
158 ApiResp::error(-1, e.to_string())
159 }
160 };
161 serde_json::to_string(&ret).unwrap()
162 }
163}
164
165#[macro_export]
167macro_rules! rollback {
168 ($resp: expr, $tx: expr, $code: expr) => {
169 if let Err(e) = $resp {
170 $tx.rollback().await?;
171 return Ok(ApiResp::error($code, e.to_string()));
172 }
173 };
174}
175
176#[macro_export]
178macro_rules! rollback_for_no_match {
179 ($resp: expr, $tx: expr, $code: expr) => {
180 match $resp {
181 Err(e) => {
182 $tx.rollback().await?;
183 return Ok(ApiResp::error($code, e.to_string()));
184 },
185 Ok(r) if r.rows_affected == 0 => {
186 $tx.rollback().await?;
187 return Ok(ApiResp::error($code, "未匹配到目标记录".to_string()));
188 },
189 _ => {}
190 }
191 };
192}
193
194#[cfg(test)]
195mod tests {
196 use serde_json::json;
197 use super::*;
198
199 #[derive(Debug, Serialize, Deserialize)]
200 struct PingPang {
201 color: String,
202 weight: f64,
203 }
204
205 #[test]
206 fn test_resp() {
207 let suc_json = ApiResp::suc().to_json();
209 println!("suc_json: {}", suc_json);
210 let orig_suc: ApiResp = serde_json::from_str(suc_json.as_str()).unwrap();
211 assert!(orig_suc.is_success());
212
213 let vals = vec![
215 PingPang {color: "white".to_string(), weight: 10.0},
216 PingPang {color: "yellow".to_string(), weight: 11.5},
217 ];
218 let suc_data = ApiResp::success(json!(vals)).to_json();
219 println!("suc_data: {}", suc_data);
220 let orig_suc_data: ApiResp = serde_json::from_str(suc_data.as_str()).unwrap();
221 assert!(orig_suc_data.is_success());
222
223 let fail_json = ApiResp::error(-1, String::from("交易出错了")).to_json();
225 println!("fail_json: {}", fail_json);
226 let orig_fail: ApiResp = serde_json::from_str(fail_json.as_str()).unwrap();
227 assert!(!orig_fail.is_success());
228 }
229}