Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API Responses

Build consistent API responses with rok-utils.

Basic Response

#![allow(unused)]
fn main() {
use serde::Serialize;

#[derive(Debug, Serialize)]
struct ApiResponse<T> {
    success: bool,
    data: Option<T>,
    error: Option<String>,
}

impl<T> ApiResponse<T> {
    fn ok(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            error: None,
        }
    }

    fn err(message: &str) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(message.to_string()),
        }
    }
}
}

JSON API Response

#![allow(unused)]
fn main() {
use serde::{Deserialize, Serialize};
use serde_json::json;
use rok_utils::str::Str;

#[derive(Debug, Serialize)]
struct ApiResponse {
    success: bool,
    message: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    data: Option<serde_json::Value>,
}

impl ApiResponse {
    fn success(message: &str) -> Self {
        Self {
            success: true,
            message: Some(message.to_string()),
            data: None,
        }
    }

    fn success_with_data(data: serde_json::Value) -> Self {
        Self {
            success: true,
            message: None,
            data: Some(data),
        }
    }

    fn error(message: &str) -> Self {
        Self {
            success: false,
            message: Some(message.to_string()),
            data: None,
        }
    }
}
}

Using with RokError

#![allow(unused)]
fn main() {
use serde::Serialize;
use rok_utils::{RokError, RokResultExt, Str};

#[derive(Debug, Serialize)]
struct ApiResponse<T> {
    success: bool,
    data: Option<T>,
    error: Option<ErrorDetail>,
}

#[derive(Debug, Serialize)]
struct ErrorDetail {
    code: String,
    message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    field: Option<String>,
}

impl ApiResponse<String> {
    fn from_result<T: Serialize>(result: Result<T, RokError>) -> Self {
        match result {
            Ok(data) => Self {
                success: true,
                data: Some(serde_json::to_value(data).unwrap()),
                error: None,
            },
            Err(err) => Self {
                success: false,
                data: None,
                error: Some(ErrorDetail {
                    code: err.code().to_string(),
                    message: err.to_string(),
                    field: None,
                }),
            },
        }
    }
}
}

Example Usage

use serde_json::json;

fn main() {
    // Success response
    let users = json!([{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]);
    let response = ApiResponse::success_with_data(users);
    println!("{}", serde_json::to_string_pretty(&response).unwrap());

    // Error response
    let err = RokError::ValidationFailure {
        field: "email".to_string(),
        reason: "Invalid format".to_string(),
    };
    let response = ApiResponse::<serde_json::Value>::from_result(Err(err));
    println!("{}", serde_json::to_string_pretty(&response).unwrap());
}