Rust配置管理库schematic_types的使用,支持类型安全的配置解析与验证

以下是关于Rust配置管理库schematic_types的使用,支持类型安全的配置解析与验证的内容:

安装方法:

  1. 在项目目录中运行以下Cargo命令:
cargo add schematic_types
  1. 或者在Cargo.toml中添加:
schematic_types = "0.10.6"

完整示例代码:

use schematic::Config;
use serde::{Deserialize, Serialize};

// 定义配置结构体
#[derive(Config, Serialize, Deserialize)]
#[config(rename_all = "camelCase")]
struct AppConfig {
    #[setting(default = 8080)]
    port: u16,
    
    #[setting(default = "localhost")]
    host: String,
    
    #[setting(default = true)]
    debug: bool,
    
    #[setting(nested)]
    database: DatabaseConfig,
}

// 嵌套配置
#[derive(Config, Serialize, Deserialize)]
#[config(rename_all = "camelCase")]
struct DatabaseConfig {
    #[setting(default = "postgres")]
    username: String,
    
    #[setting(default = "postgres")]
    password: String,
    
    #[setting(default = "localhost")]
    host: String,
    
    #[setting(default = 5432)]
    port: u16,
    
    #[setting(default = "app_db")]
    name: String,
}

fn main() {
    // 从JSON文件加载配置
    let config = AppConfig::from_file("config.json")
        .expect("Failed to load config");
    
    // 或者从TOML文件加载
    let config = AppConfig::from_toml_file("config.toml")
        .expect("Failed to load config");
    
    // 或者从YAML文件加载
    let config = AppConfig::from_yaml_file("config.yaml")
        .expect("Failed to load config");
    
    // 使用默认值创建配置
    let default_config = AppConfig::default();
    
    // 验证配置
    if let Err(errors) = config.validate() {
        eprintln!("Config validation errors: {:?}", errors);
    }
    
    // 访问配置值
    println!("App running on {}:{}", config.host, config.port);
    println!("Database: {}@{}:{}/{}", 
        config.database.username,
        config.database.host,
        config.database.port,
        config.database.name
    );
}

示例配置文件 (config.yaml):

port: 3000
host: "0.0.0.0"
debug: true
database:
  username: "admin"
  password: "secret"
  host: "db.example.com"
  port: 5432
  name: "production_db"

主要特性:

  1. 类型安全的配置解析
  2. 支持JSON、TOML和YAML格式
  3. 嵌套配置支持
  4. 默认值设置
  5. 配置验证
  6. 自动生成的Default实现

该库由Miles Johnson维护,采用MIT许可证。

以下是完整的示例demo:

// 导入必要的库
use schematic::Config;
use serde::{Deserialize, Serialize};

// 定义应用配置结构体
#[derive(Config, Serialize, Deserialize)]
#[config(rename_all = "camelCase")]
struct AppConfig {
    // 端口号,默认8080
    #[setting(default = 8080)]
    port: u16,
    
    // 主机名,默认"localhost"
    #[setting(default = "localhost")]
    host: String,
    
    // 调试模式,默认true
    #[setting(default = true)]
    debug: bool,
    
    // 嵌套数据库配置
    #[setting(nested)]
    database: DatabaseConfig,
}

// 定义数据库配置结构体
#[derive(Config, Serialize, Deserialize)]
#[config(rename_all = "camelCase")]
struct DatabaseConfig {
    // 数据库用户名,默认"postgres"
    #[setting(default = "postgres")]
    username: String,
    
    // 数据库密码,默认"postgres"
    #[setting(default = "postgres")]
    password: String,
    
    // 数据库主机,默认"localhost"
    #[setting(default = "localhost")]
    host: String,
    
    // 数据库端口,默认5432
    #[setting(default = 5432)]
    port: u16,
    
    // 数据库名称,默认"app_db"
    #[setting(default = "app_db")]
    name: String,
}

fn main() {
    // 示例1:从YAML文件加载配置
    let config = AppConfig::from_yaml_file("config.yaml")
        .expect("Failed to load config from YAML");
    
    // 示例2:使用默认配置
    let default_config = AppConfig::default();
    
    // 示例3:验证配置
    if let Err(errors) = config.validate() {
        eprintln!("配置验证错误: {:?}", errors);
    }
    
    // 示例4:访问配置值
    println!("应用运行在 {}:{}", config.host, config.port);
    println!("数据库连接: {}@{}:{}/{}", 
        config.database.username,
        config.database.host,
        config.database.port,
        config.database.name
    );
    
    // 示例5:生成TOML配置字符串
    let toml_str = default_config.to_toml().unwrap();
    println!("默认配置的TOML格式:\n{}", toml_str);
}

示例配置文件 (config.yaml):

port: 3000
host: "0.0.0.0"
debug: true
database:
  username: "admin"
  password: "secret"
  host: "db.example.com"
  port: 5432
  name: "production_db"

这个demo展示了:

  1. 如何定义配置结构体
  2. 如何设置字段默认值
  3. 如何从文件加载配置
  4. 如何使用默认配置
  5. 如何验证配置
  6. 如何访问配置值
  7. 如何将配置转换为TOML格式

1 回复

Rust配置管理库schematic_types使用指南

schematic_types是一个用于Rust的类型安全配置解析与验证库,它提供了一种声明式的方式来定义和验证配置结构。

主要特性

  • 类型安全的配置解析
  • 支持嵌套配置结构
  • 内置多种验证器
  • 支持环境变量注入
  • 支持多种配置格式(JSON, YAML等)

基本使用方法

1. 添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
schematic_types = "0.3"
serde = { version = "1.0", features = ["derive"] }

2. 定义配置结构

use schematic_types::*;
use serde::{Deserialize, Serialize};

// 应用配置结构
#[derive(Config, Serialize, Deserialize)]
struct AppConfig {
    #[setting(
        default = "localhost",  // 默认值
        validate = "schematic_types::validate::hostname"  // 使用内置主机名验证器
    )]
    host: String,
    
    #[setting(default = 8080, validate = "schematic_types::validate::port")]  // 端口验证
    port: u16,
    
    #[setting(default = true)]  // 布尔值默认值
    debug: bool,
    
    #[setting(nested)]  // 嵌套配置
    database: DatabaseConfig,
}

// 数据库配置子结构
#[derive(Config, Serialize, Deserialize)]
struct DatabaseConfig {
    #[setting(default = "postgres://user:pass@localhost/db")]  // 数据库连接字符串默认值
    url: String,
    
    #[setting(default = 5)]  // 连接池大小默认值
    pool_size: u32,
}

3. 加载和验证配置

use schematic_types::ConfigLoader;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 从文件加载配置
    let config = ConfigLoader::<AppConfig>::new()
        .file("config.yaml")?  // 加载YAML配置文件
        .load()?;  // 解析并验证
    
    println!("Server will run on {}:{}", config.host, config.port);
    
    // 或者从环境变量加载配置
    let config = ConfigLoader::<AppConfig>::new()
        .env()  // 从环境变量加载
        .load()?;
    
    Ok(())
}

高级功能

自定义验证器

#[derive(Config, Serialize, Deserialize)]
struct CustomConfig {
    #[setting(validate = "validate_api_key")]  // 使用自定义验证函数
    api_key: String,
}

// 自定义API密钥验证函数
fn validate_api_key(key: &str) -> Result<(), String> {
    if key.len() != 32 {
        Err("API key must be 32 characters long".into())
    } else {
        Ok(())
    }
}

环境变量覆盖

#[derive(Config, Serialize, Deserialize)]
struct EnvConfig {
    #[setting(env = "APP_HOST")]  // 从APP_HOST环境变量读取
    host: String,
    
    #[setting(env = "APP_PORT")]  // 从APP_PORT环境变量读取
    port: u16,
}

合并多个配置源

let config = ConfigLoader::<AppConfig>::new()
    .file("config.yaml")?  // 基础配置
    .file("config.local.yaml")?  // 本地覆盖配置
    .env()?  // 环境变量最高优先级
    .load()?;

示例配置文件

config.yaml示例:

host: "0.0.0.0"
port: 3000
debug: false
database:
  url: "postgres://user:pass@prod-db/db"
  pool_size: 10

完整示例Demo

下面是一个完整的示例,展示如何使用schematic_types从多个源加载和验证配置:

use schematic_types::*;
use serde::{Deserialize, Serialize};

// 1. 定义配置结构
#[derive(Config, Serialize, Deserialize, Debug)]
struct AppConfig {
    #[setting(
        default = "localhost",
        validate = "schematic_types::validate::hostname"
    )]
    host: String,
    
    #[setting(default = 8080, validate = "schematic_types::validate::port")]
    port: u16,
    
    #[setting(default = true)]
    debug: bool,
    
    #[setting(nested)]
    database: DatabaseConfig,
}

#[derive(Config, Serialize, Deserialize, Debug)]
struct DatabaseConfig {
    #[setting(default = "postgres://user:pass@localhost/db")]
    url: String,
    
    #[setting(default = 5)]
    pool_size: u32,
}

// 2. 自定义验证器示例
#[derive(Config, Serialize, Deserialize, Debug)]
struct CustomConfig {
    #[setting(validate = "validate_api_key")]
    api_key: String,
}

fn validate_api_key(key: &str) -> Result<(), String> {
    if key.len() != 32 {
        Err("API key must be 32 characters long".into())
    } else {
        Ok(())
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 3. 从文件加载配置
    let config = ConfigLoader::<AppConfig>::new()
        .file("config.yaml")?
        .load()?;
    
    println!("Loaded config: {:?}", config);
    
    // 4. 从环境变量加载配置
    std::env::set_var("APP_HOST", "127.0.0.1");
    std::env::set_var("APP_PORT", "8081");
    
    let env_config = ConfigLoader::<AppConfig>::new()
        .env()
        .load()?;
    
    println!("Env config: {:?}", env_config);
    
    // 5. 合并多个配置源
    let merged_config = ConfigLoader::<AppConfig>::new()
        .file("config.yaml")?
        .env()?
        .load()?;
    
    println!("Merged config: {:?}", merged_config);
    
    Ok(())
}

schematic_types通过强大的类型系统和验证机制,可以帮助开发者构建更加健壮的配置处理逻辑,减少运行时配置错误。

回到顶部