api/response/
mod.rs

1//! Standard API response wrapper.
2//!
3//! `ApiResponse<T>` enforces a consistent JSON structure for all endpoints:
4//! ```json
5//! {
6//!   "success": true|false,
7//!   "data": { ... } | null,
8//!   "message": "Description"
9//! }
10//! ```
11//! Use the provided constructors for success or error responses.
12
13use serde::Serialize;
14
15/// Standardized API response wrapper for all outgoing JSON responses.
16///
17/// This struct enforces a consistent response structure across all endpoints:
18/// ```json
19/// {
20///   "success": true,
21///   "data": { ... },
22///   "message": "Some message"
23/// }
24/// ```
25///
26/// - `T` is the type of the `data` payload.
27/// - `success` is a boolean indicating operation status.
28/// - `message` provides a human-readable context string.
29///
30/// ## Example (success):
31/// ```json
32/// {
33///   "success": true,
34///   "data": { "id": 1, "name": "Alice" },
35///   "message": "User fetched successfully"
36/// }
37/// ```
38///
39/// ## Example (error):
40/// ```json
41/// {
42///   "success": false,
43///   "data": {},
44///   "message": "User not found"
45/// }
46/// ```
47#[derive(Serialize)]
48pub struct ApiResponse<T>
49where
50    T: Serialize,
51{
52    pub success: bool,
53
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub data: Option<T>,
56
57    pub message: String,
58}
59
60impl<T> ApiResponse<T>
61where
62    T: Serialize,
63{
64    /// Constructs a success response with the given data and message.
65    ///
66    /// # Arguments
67    /// - `data`: The result payload.
68    /// - `message`: A descriptive message to accompany the success.
69    pub fn success(data: T, message: impl Into<String>) -> Self {
70        ApiResponse {
71            success: true,
72            data: Some(data),
73            message: message.into(),
74        }
75    }
76
77    /// Constructs a success response with no data, only a message.
78    ///
79    /// # Arguments
80    /// - `message`: A descriptive message to accompany the success.
81    pub fn success_without_data(message: impl Into<String>) -> Self {
82        ApiResponse {
83            success: true,
84            data: None,
85            message: message.into(),
86        }
87    }
88
89    /// Constructs an error response with a message and no `data`.
90    ///
91    /// # Arguments
92    /// - `message`: A description of the error.
93    pub fn error(message: impl Into<String>) -> Self {
94        ApiResponse {
95            success: false,
96            data: None,
97            message: message.into(),
98        }
99    }
100}