Serde で JSON のシリアライズを行う

Recipe ID: rust-014

Rust のデータ(構造体など)と、フロントエンドの JavaScript オブジェクト(JSON)を相互に変換するために、Rust では Serde (サーデ) というライブラリが標準的に使われています。
Tauri 開発においては、フロントエンドとのデータ交換の要となる非常に重要なライブラリです。

1. 構造体を JSON に変換する準備

構造体に #[derive(Serialize, Deserialize)] をつけるだけで、自動的に変換機能が追加されます。

  • Serialize: Rust -> JSON (フロントエンドへ送る時)
  • Deserialize: JSON -> Rust (フロントエンドから受け取る時)
use serde::{Deserialize, Serialize};

// この構造体は自動的にJSON変換できるようになります
#[derive(Debug, Serialize, Deserialize)]
struct User {
    id: i32,
    name: String,
}

2. フィールド名の変換 (rename)

Rust はスネークケース (user_id)、JavaScript はキャメルケース (userId) が命名規則です。
#[serde(rename_all = "camelCase")] を使うと、この変換を自動で行ってくれます。

#[derive(Serialize)]
#[serde(rename_all = "camelCase")] // 全フィールドをキャメルケースに変換
struct UserProfile {
    user_id: i32,      // JS側では "userId" になる
    first_name: String, // JS側では "firstName" になる
}

#[derive(Serialize)]
struct Config {
    // 特定のフィールドだけ名前を変えたい場合
    #[serde(rename = "isPrivate")] 
    private: bool,
}

3. デフォルト値の設定

フロントエンドからデータを受け取る際、一部のフィールドが欠けている場合にデフォルト値を埋めることができます。

#[derive(Deserialize)]
struct SearchParams {
    query: String,
    
    // JSから送られてこなかったら false にする
    #[serde(default)] 
    include_archived: bool,

    // JSから送られてこなかったら default_limit() の戻り値を使う
    #[serde(default = "default_limit")]
    limit: i32,
}

fn default_limit() -> i32 {
    10
}

4. フィールドの省略

特定の条件でフィールドを JSON に含めたくない場合に使います。
Option 型と組み合わせることが多いです。

#[derive(Serialize)]
struct ApiResonse {
    status: String,
    
    // 値が None の場合はフィールドごと消す(nullとして送らない)
    #[serde(skip_serializing_if = "Option::is_none")]
    error_message: Option<String>,
}