Types
mik-sdk uses derive macros to define type-safe inputs (path, query, body) and outputs. These types are automatically parsed, validated, and documented in the OpenAPI schema.
Overview
Section titled “Overview”| Macro | Purpose | JSON Serialization |
|---|---|---|
#[derive(Type)] | Request/response body | Yes |
#[derive(Query)] | Query string parameters | No |
#[derive(Path)] | URL path parameters | No |
Type (JSON Body)
Section titled “Type (JSON Body)”Use #[derive(Type)] for JSON request bodies and response types:
#[derive(Type)]pub struct CreateUserInput { pub name: String, pub email: String, pub age: Option<i32>,}
#[derive(Type)]pub struct User { pub id: String, pub name: String, pub email: String,}
routes! { POST "/users" => create_user(body: CreateUserInput) -> User,}
fn create_user(body: CreateUserInput, _req: &Request) -> Response { let id = random::uuid(); ok!({ "id": id, "name": body.name, "email": body.email })}Supported Field Types
Section titled “Supported Field Types”| Type | JSON Type | Example |
|---|---|---|
String | string | "hello" |
i32, i64 | number | 42 |
u32, u64 | number | 42 |
f32, f64 | number | 3.14 |
bool | boolean | true |
Option<T> | T or null | null or value |
Vec<T> | array | [1, 2, 3] |
Nested Type | object | { "name": "Alice" } |
| Enum (see below) | string | "active" |
Field Attributes
Section titled “Field Attributes”Add constraints and metadata with #[field(...)]:
#[derive(Type)]pub struct CreatePostInput { // Length constraints #[field(min = 1, max = 200)] pub title: String,
// Rename JSON field #[field(rename = "bodyContent")] pub body: String,
// Format hint (for OpenAPI) #[field(format = "email")] pub author_email: String,
// Pattern validation (for OpenAPI) #[field(pattern = "^[a-z0-9-]+$")] pub slug: String,
// Documentation #[field(docs = "Tags for categorization")] pub tags: Vec<String>,}| Attribute | Applies To | Description |
|---|---|---|
min | String, Vec, numbers | Minimum length/value/items |
max | String, Vec, numbers | Maximum length/value/items |
format | String | OpenAPI format hint |
pattern | String | Regex pattern |
rename | Any | JSON field name |
docs | Any | OpenAPI description |
Query (Query String)
Section titled “Query (Query String)”Use #[derive(Query)] for URL query parameters:
#[derive(Query)]pub struct SearchQuery { // Optional parameter pub q: Option<String>,
// With default value #[field(default = 1)] pub page: u32,
// With default and max constraint #[field(default = 20, max = 100)] pub limit: u32,}
routes! { GET "/users" => list_users(query: SearchQuery),}
fn list_users(query: SearchQuery, _req: &Request) -> Response { ok!({ "search": query.q, "page": query.page, "limit": query.limit })}Request: GET /users?q=alice&page=2&limit=50
Query-Specific Attributes
Section titled “Query-Specific Attributes”| Attribute | Description |
|---|---|
default | Default value if parameter is missing |
max | Maximum allowed value |
min | Minimum allowed value |
Path (URL Parameters)
Section titled “Path (URL Parameters)”Use #[derive(Path)] for URL path parameters:
#[derive(Path)]pub struct UserPath { pub id: String, // Matches {id} in route}
#[derive(Path)]pub struct OrgUserPath { pub org_id: String, // Matches {org_id} pub user_id: String, // Matches {user_id}}
routes! { GET "/users/{id}" => get_user(path: UserPath), GET "/orgs/{org_id}/users/{user_id}" => get_org_user(path: OrgUserPath),}
fn get_user(path: UserPath, _req: &Request) -> Response { ok!({ "id": path.id })}
fn get_org_user(path: OrgUserPath, _req: &Request) -> Response { ok!({ "org_id": path.org_id, "user_id": path.user_id })}Use #[derive(Type)] on enums to serialize them as JSON strings. Only unit variants (no fields) are supported.
#[derive(Type)]pub enum Status { Active, // serializes as "active" Inactive, // serializes as "inactive" Pending, // serializes as "pending"}
#[derive(Type)]pub enum Priority { #[field(rename = "HIGH")] High, #[field(rename = "MEDIUM")] Medium, #[field(rename = "LOW")] Low,}Enum Behavior
Section titled “Enum Behavior”- Variants are converted from
PascalCasetosnake_caseby default (SuperAdmin→"super_admin") - Use
#[field(rename = "...")]on variants to customize the JSON string - Invalid values return a helpful error listing all valid options
- OpenAPI schema is generated as
{ "type": "string", "enum": ["active", "inactive", "pending"] }
Using Enums in Structs
Section titled “Using Enums in Structs”Enums can be used as fields in other types:
#[derive(Type)]pub struct Task { pub id: String, pub title: String, pub status: Status, pub priority: Priority,}
#[derive(Type)]pub struct CreateTaskInput { pub title: String, pub status: Option<Status>, // Optional enum field pub priority: Priority,}
routes! { POST "/tasks" => create_task(body: CreateTaskInput) -> Task,}
fn create_task(body: CreateTaskInput, _req: &Request) -> Response { ok!({ "id": random::uuid(), "title": body.title, "status": body.status.unwrap_or(Status::Pending), "priority": body.priority })}Example request:
{ "title": "Review PR", "status": "active", "priority": "HIGH"}Example response:
{ "id": "550e8400-e29b-41d4-a716-446655440000", "title": "Review PR", "status": "active", "priority": "HIGH"}Combining Inputs
Section titled “Combining Inputs”Handlers can receive multiple typed inputs:
#[derive(Path)]pub struct TaskPath { pub id: String,}
#[derive(Query)]pub struct TaskQuery { #[field(default = false)] pub include_history: bool,}
#[derive(Type)]pub struct UpdateTaskInput { pub title: Option<String>, pub status: Option<Status>,}
routes! { GET "/tasks/{id}" => get_task(path: TaskPath, query: TaskQuery), PUT "/tasks/{id}" => update_task(path: TaskPath, body: UpdateTaskInput),}
fn get_task(path: TaskPath, query: TaskQuery, _req: &Request) -> Response { ok!({ "id": path.id, "include_history": query.include_history })}
fn update_task(path: TaskPath, body: UpdateTaskInput, _req: &Request) -> Response { ok!({ "id": path.id, "updated_title": body.title, "updated_status": body.status })}Validation Errors
Section titled “Validation Errors”When parsing or validation fails, mik-sdk returns an RFC 7807 Problem Details response:
{ "type": "urn:problem:validation", "title": "Validation Error", "status": 400, "detail": "Invalid request body", "errors": [ { "field": "name", "message": "field is required" }, { "field": "email", "message": "invalid format" } ]}For enums, invalid values produce a helpful error:
{ "type": "urn:problem:validation", "title": "Validation Error", "status": 400, "detail": "Invalid request body", "errors": [ { "field": "status", "message": "unknown enum variant \"invalid\". Valid values: \"active\", \"inactive\", \"pending\"" } ]}Next Steps
Section titled “Next Steps”- Routing - Route definitions and patterns
- Responses - Response macros
- Quick Reference - Complete API reference