serde_json
シリアライゼーションライブラリ
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使用時)
参考ページ
- GitHubリポジトリ: https://github.com/serde-rs/json
- ドキュメント: https://docs.rs/serde_json/
- Serde公式サイト: https://serde.rs/
書き方の例
基本的な使用方法
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"),
}
}
}