myc_http_tools/utils/
json_response.rs1use actix_web::HttpResponse;
2use serde::Serialize;
3use std::fmt::{Display, Formatter, Result as FmtResult};
4use utoipa::{ToResponse, ToSchema};
5
6#[derive(Debug, Serialize, ToResponse, ToSchema)]
7#[serde(rename_all = "camelCase")]
8pub struct HttpJsonResponse {
9 #[serde(skip_serializing_if = "Option::is_none")]
10 msg: Option<String>,
11
12 #[serde(skip_serializing_if = "Option::is_none")]
13 code: Option<String>,
14
15 #[serde(skip_serializing_if = "Option::is_none")]
16 body: Option<String>,
17}
18
19impl HttpJsonResponse {
20 pub fn new_message<T: ToString>(msg: T) -> Self {
21 Self {
22 msg: msg.to_string().into(),
23 code: None,
24 body: None,
25 }
26 }
27
28 pub fn new_body<T: Serialize>(body: T) -> Result<Self, HttpResponse> {
29 match serde_json::to_string(&body) {
30 Err(err) => {
31 let json_error = HttpJsonResponse::new_message(err.to_string());
32
33 return Err(
34 HttpResponse::InternalServerError().json(json_error)
35 );
36 }
37 Ok(body) => Ok(Self {
38 msg: None,
39 code: None,
40 body: Some(body),
41 }),
42 }
43 }
44
45 pub fn new_vec_body<T: Serialize>(
46 body: Vec<T>,
47 ) -> Result<Self, HttpResponse> {
48 match serde_json::to_string(&body) {
49 Err(err) => {
50 let json_error = HttpJsonResponse::new_message(err.to_string());
51
52 return Err(
53 HttpResponse::InternalServerError().json(json_error)
54 );
55 }
56 Ok(body) => Ok(Self {
57 msg: None,
58 code: None,
59 body: Some(body),
60 }),
61 }
62 }
63
64 pub fn with_code<T: ToString>(&self, code: T) -> Self {
65 Self {
66 msg: self.msg.to_owned(),
67 code: Some(code.to_string()),
68 body: self.body.to_owned(),
69 }
70 }
71
72 pub fn with_code_str(&self, code: &'static str) -> Self {
73 Self {
74 msg: self.msg.to_owned(),
75 code: Some(code.to_string()),
76 body: self.body.to_owned(),
77 }
78 }
79
80 pub fn with_body(&self, body: String) -> Self {
81 Self {
82 msg: self.msg.to_owned(),
83 code: self.code.to_owned(),
84 body: Some(body),
85 }
86 }
87
88 pub fn with_serializable_body<T: Serialize>(
89 &self,
90 body: T,
91 ) -> Result<Self, HttpResponse> {
92 match serde_json::to_string(&body) {
93 Err(err) => {
94 let json_error = HttpJsonResponse::new_message(err.to_string());
95
96 return Err(
97 HttpResponse::InternalServerError().json(json_error)
98 );
99 }
100 Ok(body) => Ok(Self {
101 msg: self.msg.to_owned(),
102 code: self.code.to_owned(),
103 body: Some(body),
104 }),
105 }
106 }
107}
108
109impl Display for HttpJsonResponse {
110 fn fmt(&self, f: &mut Formatter) -> FmtResult {
111 let msg = self.msg.to_owned().unwrap_or("no message".to_string());
112
113 if self.code.is_some() {
114 return write!(f, "{}: {}", self.code.as_ref().unwrap(), msg);
115 }
116
117 write!(f, "{}", msg)
118 }
119}
120
121#[cfg(test)]
126mod tests {
127
128 use super::*;
129
130 #[test]
131 fn test_json_error() {
132 let json_error = HttpJsonResponse::new_message("test".to_string());
133 assert_eq!(json_error.msg, Some("test".to_string()));
134 assert_eq!(json_error.code, None);
135 }
136
137 #[test]
138 fn test_json_error_code() {
139 let json_error = HttpJsonResponse::new_message("test".to_string())
140 .with_code_str("code");
141 assert_eq!(json_error.msg, Some("test".to_string()));
142 assert_eq!(json_error.code, Some("code".to_string()));
143 }
144
145 #[test]
146 fn test_json_error_display() {
147 let json_error = HttpJsonResponse::new_message("test".to_string());
148 assert_eq!(format!("{}", json_error), "test");
149
150 let json_error = HttpJsonResponse::new_message("test".to_string())
151 .with_code_str("code");
152 assert_eq!(format!("{}", json_error), "code: test");
153 }
154}