数据序列化
前后端之间的数据通过 JSON 格式传输。Rust 端使用 serde + serde_json 进行序列化/反序列化。
基本原理
TypeScript 对象 → JSON → Rust 结构体
Rust 结构体 → JSON → TypeScript 对象
Rust 端定义
// src-tauri/src/models/mod.rs
use serde::{Deserialize, Serialize};
/// 应用配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
pub key: String,
pub value: String,
}
/// 系统信息
#[derive(Debug, Clone, Serialize)]
pub struct SystemInfo {
pub os: String,
pub arch: String,
pub app_version: String,
pub data_dir: String,
}
AppConfig 只暴露 key / value 两个字段;数据库表 app_config 里的 created_at / updated_at / deleted_at 是存储细节,不传给前端。
TypeScript 端对应类型
// src/types/config.ts
/** 应用配置 */
export interface AppConfig {
key: string;
value: string;
}
// src/types/system.ts
/** 系统信息 */
export interface SystemInfo {
os: string;
arch: string;
appVersion: string;
dataDir: string;
}
模板里的 SystemInfo 两端命名不一致
Rust 的 SystemInfo 没有加 #[serde(rename_all = "camelCase")],序列化出的字段是 app_version / data_dir;而 TypeScript 类型写的是 appVersion / dataDir。这种情况下前端读 info.appVersion 会得到 undefined。照着写新结构体时,二选一:给 Rust 结构体加 rename_all = "camelCase"(推荐,见下一节),或让 TypeScript 字段也用 snake_case。
命名转换
Rust 使用 snake_case,TypeScript 使用 camelCase。可以用 serde 属性控制:
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UserInfo {
pub user_name: String, // → JSON: "userName"
pub email_addr: String, // → JSON: "emailAddr"
}
Command 参数名会自动转换
Tauri 2 默认把 Command 参数按 camelCase 暴露给前端:Rust 参数 user_id: String 在前端要写成 invoke('xxx', { userId })。这一转换只作用于顶层参数名,参数里的结构体字段仍按 serde 规则(上面的 rename_all)处理。
Command 中使用
// src-tauri/src/commands/system.rs
use tauri::Manager;
use crate::error::CommandError;
use crate::models::SystemInfo;
/// 获取系统信息
#[tauri::command]
pub fn get_system_info(app: tauri::AppHandle) -> Result<SystemInfo, CommandError> {
let data_dir = app
.path()
.app_data_dir()
.map(|p| p.to_string_lossy().into_owned())
.unwrap_or_else(|_| "unknown".into());
Ok(SystemInfo {
os: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
app_version: app.package_info().version.to_string(),
data_dir,
})
}
错误类型同样走序列化:CommandError 派生了 Serialize,失败时以 { "code": "...", "message": "..." } 的结构交给前端(见 IPC 通信)。
注意事项
类型对齐
确保 Rust 结构体和 TypeScript 接口的字段名和类型严格对齐,否则会导致运行时反序列化错误或前端读到 undefined。
i64/i32→number(超过2^53的i64在 JS 中会丢精度,这类 ID 建议用String传)String→stringbool→booleanVec<T>→T[]Option<T>→T | nullHashMap<String, T>→Record<string, T>()→void(如set_config返回Result<(), CommandError>,前端对应invoke<void>)