serde_json

シリアライゼーションRustJSONSerdeストリーミングAPI

シリアライゼーションライブラリ

serde_json

概要

serde_jsonは、Rust用の高速で柔軟なJSONシリアライゼーション・デシリアライゼーションライブラリです。Serdeフレームワークと統合され、Rustのデータ構造とJSONの相互変換を型安全に行えます。ストリーミングAPIや整形出力、動的なJSON操作など、JSON処理に必要な機能を幅広くサポートしています。

詳細

serde_jsonは、SerdeフレームワークのためのJSON実装で、Rustでの強い型付けされたデータ構造のJSON変換を効率的に行います。C/C++の最速のJSONライブラリと同等またはそれ以上のパフォーマンスを実現しています。

主な特徴:

  • 高速処理: 500-1000 MB/秒のデシリアライゼーション、600-900 MB/秒のシリアライゼーション速度
  • ストリーミングAPI: 大規模なJSONデータの効率的な処理
  • Pretty Printing: 読みやすい整形出力のサポート
  • 動的JSON操作: serde_json::Value型による柔軟なJSON操作
  • マクロサポート: json!マクロによる直感的なJSON構築

主要な機能:

  • to_string: JSONへのシリアライゼーション
  • to_string_pretty: 整形済みJSONへのシリアライゼーション
  • to_writer: ファイルやネットワークストリームへの直接書き込み
  • from_str: JSONからのデシリアライゼーション
  • StreamDeserializer: 複数のJSON値の連続処理

技術的詳細:

  • ゼロコピーデシリアライゼーションのサポート
  • カスタムPrettyFormatterによるインデント制御
  • no-std環境対応("alloc"フィーチャー使用時)
  • 任意精度数値のサポート

メリット・デメリット

メリット

  • 業界トップクラスのパフォーマンス
  • Serdeエコシステムとの完全な統合
  • 豊富な機能セット(ストリーミング、整形出力など)
  • 優れたエラーメッセージとデバッグ体験
  • 活発なメンテナンスとコミュニティサポート
  • 標準的なJSON仕様への準拠

デメリット

  • Serde依存により初期学習コストがある
  • JSONの制限(例:コメント非対応、キーの順序保証なし)
  • カスタムシリアライゼーションの実装は複雑
  • コンパイル時間への影響(derive使用時)

参考ページ

書き方の例

基本的な使用方法

use serde::{Serialize, Deserialize};
use serde_json;

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

fn main() -> Result<(), serde_json::Error> {
    let person = Person {
        name: "田中太郎".to_string(),
        age: 30,
        email: "[email protected]".to_string(),
    };
    
    // JSONへシリアライズ
    let json = serde_json::to_string(&person)?;
    println!("JSON: {}", json);
    
    // 整形済みJSONへシリアライズ
    let pretty_json = serde_json::to_string_pretty(&person)?;
    println!("Pretty JSON:\n{}", pretty_json);
    
    // デシリアライズ
    let deserialized: Person = serde_json::from_str(&json)?;
    println!("Deserialized: {:?}", deserialized);
    
    Ok(())
}

json!マクロの使用

use serde_json::{json, Value};

fn main() {
    // json!マクロで動的にJSON構築
    let data = json!({
        "name": "プロジェクト設定",
        "version": "1.0.0",
        "dependencies": {
            "serde": "1.0",
            "tokio": "1.0"
        },
        "features": ["async", "json", "yaml"],
        "active": true,
        "count": 42
    });
    
    println!("{}", serde_json::to_string_pretty(&data).unwrap());
    
    // 値へのアクセス
    println!("Name: {}", data["name"]);
    println!("Version: {}", data["version"]);
    
    // 動的な値の変更
    let mut value = data;
    value["count"] = json!(100);
    value["features"].as_array_mut().unwrap().push(json!("new_feature"));
}

ストリーミングAPI

use serde::{Serialize, Deserialize};
use serde_json::Deserializer;

#[derive(Serialize, Deserialize, Debug)]
struct LogEntry {
    timestamp: String,
    level: String,
    message: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 複数のJSON値を含む文字列
    let json_stream = r#"
        {"timestamp": "2024-01-01T10:00:00Z", "level": "INFO", "message": "Server started"}
        {"timestamp": "2024-01-01T10:00:01Z", "level": "DEBUG", "message": "Connection established"}
        {"timestamp": "2024-01-01T10:00:02Z", "level": "ERROR", "message": "Failed to process request"}
    "#;
    
    // ストリーミングデシリアライザーの作成
    let stream = Deserializer::from_str(json_stream).into_iter::<LogEntry>();
    
    for item in stream {
        match item {
            Ok(entry) => println!("{:?}", entry),
            Err(e) => eprintln!("Error: {}", e),
        }
    }
    
    Ok(())
}

ファイルI/O

use serde::{Serialize, Deserialize};
use std::fs::File;
use std::io::{BufReader, BufWriter};

#[derive(Serialize, Deserialize, Debug)]
struct Config {
    database_url: String,
    port: u16,
    workers: usize,
    features: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Config {
        database_url: "postgres://localhost/mydb".to_string(),
        port: 8080,
        workers: 4,
        features: vec!["auth".to_string(), "api".to_string()],
    };
    
    // ファイルへの書き込み
    let file = File::create("config.json")?;
    let writer = BufWriter::new(file);
    serde_json::to_writer_pretty(writer, &config)?;
    
    // ファイルからの読み込み
    let file = File::open("config.json")?;
    let reader = BufReader::new(file);
    let loaded_config: Config = serde_json::from_reader(reader)?;
    
    println!("Loaded config: {:?}", loaded_config);
    
    Ok(())
}

カスタムPretty Printing

use serde_json::{to_string_pretty, Value};
use serde_json::ser::PrettyFormatter;

fn main() -> Result<(), serde_json::Error> {
    let data = serde_json::json!({
        "users": [
            {"id": 1, "name": "Alice"},
            {"id": 2, "name": "Bob"}
        ],
        "settings": {
            "theme": "dark",
            "language": "ja"
        }
    });
    
    // デフォルトの整形(2スペース)
    let pretty = to_string_pretty(&data)?;
    println!("Default formatting:\n{}", pretty);
    
    // カスタムフォーマッター(4スペース)
    let buf = Vec::new();
    let formatter = PrettyFormatter::with_indent(b"    ");
    let mut ser = serde_json::Serializer::with_formatter(buf, formatter);
    data.serialize(&mut ser)?;
    let result = String::from_utf8(ser.into_inner()).unwrap();
    println!("\nCustom formatting (4 spaces):\n{}", result);
    
    Ok(())
}

エラーハンドリング

use serde::{Serialize, Deserialize};
use serde_json::{Error, Result};

#[derive(Serialize, Deserialize, Debug)]
struct User {
    id: u64,
    name: String,
    age: Option<u32>,
}

fn parse_user(json: &str) -> Result<User> {
    serde_json::from_str(json)
}

fn main() {
    // 正常なJSON
    let valid_json = r#"{"id": 1, "name": "Alice", "age": 30}"#;
    match parse_user(valid_json) {
        Ok(user) => println!("Parsed user: {:?}", user),
        Err(e) => eprintln!("Error: {}", e),
    }
    
    // 不正なJSON(型の不一致)
    let invalid_json = r#"{"id": "not_a_number", "name": "Bob"}"#;
    match parse_user(invalid_json) {
        Ok(user) => println!("Parsed user: {:?}", user),
        Err(e) => {
            eprintln!("Error: {}", e);
            eprintln!("Line: {}, Column: {}", e.line(), e.column());
        }
    }
    
    // 不完全なJSON
    let incomplete_json = r#"{"id": 1, "name": "Charlie""#;
    if let Err(e) = parse_user(incomplete_json) {
        eprintln!("Parse error: {}", e);
        // エラーの種類を判定
        use serde_json::error::Category;
        match e.classify() {
            Category::Io => eprintln!("IO error"),
            Category::Syntax => eprintln!("Syntax error"),
            Category::Data => eprintln!("Data error"),
            Category::Eof => eprintln!("Unexpected end of input"),
        }
    }
}