JSON 設定ファイルから Rust 構造体へ
JSON 設定ファイルから強い型付けの Rust 構造体を生成します。デフォルト値、検証、環境変数とのマージのパターンも解説します。
Real-World
詳細な説明
JSON 設定ファイルを型付き構造体として読み込む
CLI ツールやサービスの多くは、JSON ファイルから実行時設定を読み込みます。そのファイルの構造を Rust 構造体に変換すれば、すべてのキーを compile-time に検証できる上、serde のおかげでデフォルト値も簡単に与えられます。
設定ファイルの例
{
"server": {
"host": "0.0.0.0",
"port": 8080,
"workers": 4
},
"database": {
"url": "postgres://localhost/myapp",
"pool_size": 10,
"timeout_seconds": 30
},
"logging": {
"level": "info",
"format": "json"
},
"features": {
"experimental_search": false,
"rate_limiting": true
}
}
生成される Rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
pub server: Server,
pub database: Database,
pub logging: Logging,
pub features: Features,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Server {
pub host: String,
pub port: i32,
pub workers: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Database {
pub url: String,
pub pool_size: i32,
pub timeout_seconds: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Logging {
pub level: String,
pub format: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Features {
pub experimental_search: bool,
pub rate_limiting: bool,
}
デフォルト値の追加
設定ファイル全体や一部が省略可能なら、#[serde(default)] で囲ってください。
impl Default for Server {
fn default() -> Self {
Self {
host: "127.0.0.1".into(),
port: 8080,
workers: 1,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AppConfig {
#[serde(default)]
pub server: Server,
// ...
}
これで欠けたセクションは Default 実装にフォールバックし、エラーで止まりません。
ファイルの読み込み
let raw = std::fs::read_to_string("config.json")?;
let config: AppConfig = serde_json::from_str(&raw)?;
文字列を enum に昇格させる
logging.level は enum 化(Trace、Debug、Info、Warn、Error)に最適なフィールドです。最初に struct を生成したあと、enum-from-string のレシピに従って有効な値を型で固定するとよいでしょう。
ユースケース
Web サーバ、CLI ツール、組み込みシステム、ゲームエンジンなど、設定をパースするあらゆるソフトウェアが恩恵を受けます。設定ファイルの typo が、ランタイムでの謎の挙動ではなく明示的なデシリアライズエラーになります。