Serde Support

metaxy respects serde attributes on your Rust types and translates them into the corresponding TypeScript output. This ensures the generated types match exactly what your API serializes.

rename_all

Apply a naming convention to all fields or variants. Supported: camelCase, snake_case, PascalCase, SCREAMING_SNAKE_CASE, kebab-case, lowercase, UPPERCASE.

rust
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UserProfile {
    pub user_name: String,
    pub avatar_url: Option<String>,
    #[serde(skip)]
    pub internal_score: f64,
}
ts
interface UserProfile {
  userName: string;       // renamed to camelCase
  avatarUrl: string | null;
  // internal_score omitted (skip)
}

rename

Override individual field or variant names. Takes priority over rename_all.

rust
#[derive(Serialize)]
pub struct Config {
    #[serde(rename = "api-key")]
    pub api_key: String,
    #[serde(rename = "base_url")]
    pub endpoint: String,
}
ts
interface Config {
  "api-key": string;   // exact rename
  base_url: string;    // exact rename
}

flatten

Merge a nested struct's fields into the parent. Produces a TypeScript intersection type.

rust
#[derive(Serialize)]
pub struct Timestamped {
    pub created_at: u64,
    pub updated_at: u64,
}

#[derive(Serialize)]
pub struct User {
    pub name: String,
    #[serde(flatten)]
    pub timestamps: Timestamped,
}
ts
interface Timestamped {
  created_at: number;
  updated_at: number;
}

type User = {
  name: string;
} & Timestamped;

Enum Tagging

All four serde enum representations are supported. The default is externally tagged.

External (default)

rust
// Default: externally tagged
#[derive(Serialize)]
pub enum Shape {
    Circle { radius: f64 },
    Rect { w: f64, h: f64 },
}
ts
type Shape =
  | { Circle: { radius: number } }
  | { Rect: { w: number; h: number } };

Internal tag = "..."

rust
#[derive(Serialize)]
#[serde(tag = "type")]
pub enum Event {
    Click { x: i32, y: i32 },
    Scroll { delta: f64 },
}
ts
type Event =
  | { type: "Click"; x: number; y: number }
  | { type: "Scroll"; delta: number };

Adjacent tag + content

rust
#[derive(Serialize)]
#[serde(tag = "t", content = "c")]
pub enum Message {
    Text(String),
    Data { payload: Vec<u8> },
}
ts
type Message =
  | { t: "Text"; c: string }
  | { t: "Data"; c: { payload: number[] } };

Untagged

rust
#[derive(Serialize)]
#[serde(untagged)]
pub enum StringOrNumber {
    Str(String),
    Num(f64),
}
ts
type StringOrNumber = string | number;

visit GitHub to learn more about metaxy