あっぽログ
← 記事一覧に戻る

RustのSerde入門:JSONシリアライズ・デシリアライズを使いこなす

Serdeとは何か

WebアプリケーションやAPIを開発していると、JSONデータを扱う場面が頻繁にあります。RustではSerdeというクレートがデファクトスタンダードになっており、構造体とJSONなどの形式を相互変換する処理を非常に簡潔に記述できます。

SerdeはSerialize(シリアライズ:RustデータをJSONなどに変換)とDeserde(デシリアライズ:JSONなどをRustデータに変換)の2方向をカバーしています。

この記事ではSerdeの基本的な使い方から、フィールド名の変換・デフォルト値の設定・ネストした構造体の扱いまでを順を追って解説します。


セットアップ

まずCargo.tomlにSerdeとJSON用のクレートserde_jsonを追加します。

[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"

features = ["derive"]を指定することで、マクロを使った自動導出(derive)が使えるようになります。


基本的なシリアライズ・デシリアライズ

構造体へのderive

Serdeで最もよく使うパターンが#[derive(Serialize, Deserialize)]アトリビュートです。構造体に付与するだけで変換処理が自動生成されます。

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct User {
    id: u32,
    name: String,
    email: String,
}

構造体 → JSON(シリアライズ)

serde_json::to_string()で構造体をJSON文字列に変換できます。

fn main() {
    let user = User {
        id: 1,
        name: String::from("Alice"),
        email: String::from("alice@example.com"),
    };

    let json = serde_json::to_string(&user).unwrap();
    println!("{}", json);
    // {"id":1,"name":"Alice","email":"alice@example.com"}

    // 見やすく整形したい場合
    let pretty = serde_json::to_string_pretty(&user).unwrap();
    println!("{}", pretty);
}

JSON → 構造体(デシリアライズ)

serde_json::from_str()でJSON文字列を構造体に変換できます。

fn main() {
    let json = r#"{"id":2,"name":"Bob","email":"bob@example.com"}"#;

    let user: User = serde_json::from_str(json).unwrap();
    println!("{:?}", user);
    // User { id: 2, name: "Bob", email: "bob@example.com" }
}

よく使うSerdeアトリビュート

フィールド名をスネークケース ↔ キャメルケースに変換する

APIのレスポンスではcamelCaseのキー名が一般的です。#[serde(rename_all = "camelCase")]を使えば、Rust側はスネークケースのまま扱えます。

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Article {
    article_id: u32,
    title: String,
    published_at: String,
}

fn main() {
    let article = Article {
        article_id: 10,
        title: String::from("Rust入門"),
        published_at: String::from("2026-08-16"),
    };

    let json = serde_json::to_string(&article).unwrap();
    println!("{}", json);
    // {"articleId":10,"title":"Rust入門","publishedAt":"2026-08-16"}
}

特定のフィールドをスキップする

パスワードなど、シリアライズ時に含めたくないフィールドには#[serde(skip_serializing)]を使います。

#[derive(Debug, Serialize, Deserialize)]
struct Account {
    id: u32,
    username: String,
    #[serde(skip_serializing)]
    password_hash: String,
}

デフォルト値を設定する

JSONにキーが存在しない場合に使うデフォルト値は#[serde(default)]で設定できます。

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    host: String,
    #[serde(default = "default_port")]
    port: u16,
}

fn default_port() -> u16 {
    8080
}

fn main() {
    let json = r#"{"host":"localhost"}"#;
    let config: Config = serde_json::from_str(json).unwrap();
    println!("{:?}", config);
    // Config { host: "localhost", port: 8080 }
}

ネストした構造体の扱い

構造体が別の構造体をフィールドに持つ場合も、両方にderiveを付ければ自動的にネストされたJSONとして変換されます。

#[derive(Debug, Serialize, Deserialize)]
struct Address {
    city: String,
    zip: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Person {
    name: String,
    address: Address,
}

fn main() {
    let json = r#"{
        "name": "Carol",
        "address": {
            "city": "Tokyo",
            "zip": "100-0001"
        }
    }"#;

    let person: Person = serde_json::from_str(json).unwrap();
    println!("{}", person.address.city); // Tokyo
}

エラーハンドリング

実際のコードではunwrap()の代わりに?演算子やmatchでエラーを適切に処理しましょう。

use serde_json::Error;

fn parse_user(json: &str) -> Result<User, Error> {
    let user: User = serde_json::from_str(json)?;
    Ok(user)
}

fn main() {
    let invalid_json = r#"{"id": "not_a_number"}"#;
    match parse_user(invalid_json) {
        Ok(user) => println!("{:?}", user),
        Err(e) => eprintln!("パースエラー: {}", e),
    }
}

まとめ

SerdeはRustにおけるデータ変換の中心的なクレートです。今回のポイントを振り返ります。

操作関数・アトリビュート
シリアライズserde_json::to_string()
デシリアライズserde_json::from_str()
フィールド名変換#[serde(rename_all = "camelCase")]
フィールドのスキップ#[serde(skip_serializing)]
デフォルト値#[serde(default = "関数名")]

ActixやAxumなどのWebフレームワークでもSerdeは内部的に使われており、使い方を覚えておくと実践的なRust開発で大きな助けになります。ぜひ手元で動かして試してみてください。

← 記事一覧に戻る