Rust近端数据校验宏库near-schema-checker-macro的使用,实现高效Schema验证与类型安全的Rust开发
Rust近端数据校验宏库near-schema-checker-macro的使用,实现高效Schema验证与类型安全的Rust开发
near-schema-checker-macro是一个用于NEAR协议开发的Rust宏库,它提供了高效的Schema验证和类型安全开发支持。
安装
在项目目录中运行以下Cargo命令:
cargo add near-schema-checker-macro
或在Cargo.toml中添加以下行:
near-schema-checker-macro = "0.30.3"
使用示例
以下是一个使用near-schema-checker-macro进行数据验证的完整示例:
use near_schema_checker_macro::near_schema;
// 定义一个带有Schema验证的结构体
#[near_schema]
#[derive(Debug)]
struct UserProfile {
#[validate(length(min = 3, max = 32))]
username: String,
#[validate(range(min = 18, max = 120))]
age: u8,
#[validate(email)]
email: String,
#[validate(custom = "validate_timestamp")]
created_at: u64,
}
// 自定义验证函数
fn validate_timestamp(timestamp: &u64) -> Result<(), String> {
if *timestamp > 1609459200 { // 2021-01-01
Ok(())
} else {
Err("Timestamp too old".to_string())
}
}
fn main() {
// 正确数据示例
let valid_profile = UserProfile {
username: "alice".to_string(),
age: 25,
email: "alice@example.com".to_string(),
created_at: 1640995200, // 2022-01-01
};
// 验证并打印结果
match valid_profile.validate() {
Ok(_) => println!("Profile is valid!"),
Err(err) => println!("Validation error: {}", err),
}
// 错误数据示例
let invalid_profile = UserProfile {
username: "a".to_string(), // 太短
age: 121, // 超出范围
email: "invalid-email".to_string(), // 无效邮箱
created_at: 1577836800, // 2020-01-01
};
// 验证并打印所有错误
if let Err(errors) = invalid_profile.validate() {
for error in errors {
println!("Field '{}': {}", error.field, error.message);
}
}
}
完整示例
以下是near-schema-checker-macro的另一个完整示例,展示如何验证更复杂的数据结构:
use near_schema_checker_macro::near_schema;
use serde::{Serialize, Deserialize};
// 定义带验证的子结构体
#[near_schema]
#[derive(Debug, Serialize, Deserialize)]
struct Address {
#[validate(length(min = 5, max = 100))]
street: String,
#[validate(regex = r"^[A-Z]{2}$")]
state: String,
#[validate(range(min = 1000, max = 99999))]
zip_code: u32,
}
// 定义主结构体
#[near_schema]
#[derive(Debug, Serialize, Deserialize)]
struct BusinessProfile {
#[validate(length(min = 2, max = 50))]
name: String,
#[validate(custom = "validate_tax_id")]
tax_id: String,
#[validate]
address: Address,
#[validate(items)]
employees: Vec<Employee>,
}
// 定义员工结构体
#[near_schema]
#[derive(Debug, Serialize, Deserialize)]
struct Employee {
#[validate(length(min = 3, max = 50))]
name: String,
#[validate(range(min = 18, max = 70))]
age: u8,
#[validate(email)]
email: String,
}
// 自定义税号验证函数
fn validate_tax_id(tax_id: &str) -> Result<(), String> {
if tax_id.len() == 10 && tax_id.chars().all(char::is_alphanumeric) {
Ok(())
} else {
Err("Tax ID must be 10 alphanumeric characters".to_string())
}
}
fn main() {
// 创建有效商业资料
let valid_business = BusinessProfile {
name: "Tech Corp".to_string(),
tax_id: "ABC123XYZ9".to_string(),
address: Address {
street: "123 Main St".to_string(),
state: "NY".to_string(),
zip_code: 10001,
},
employees: vec![
Employee {
name: "Alice Smith".to_string(),
age: 30,
email: "alice@techcorp.com".to_string(),
},
Employee {
name: "Bob Johnson".to_string(),
age: 28,
email: "bob@techcorp.com".to_string(),
},
],
};
// 验证有效数据
match valid_business.validate() {
Ok(_) => println!("Business profile is valid!"),
Err(err) => println!("Validation error: {}", err),
}
// 创建无效商业资料
let invalid_business = BusinessProfile {
name: "T".to_string(), // 名称太短
tax_id: "123".to_string(), // 无效税号
address: Address {
street: "a".to_string(), // 街道太短
state: "New York".to_string(), // 州代码太长
zip_code: 999999, // 邮编超出范围
},
employees: vec![
Employee {
name: "A".to_string(), // 名字太短
age: 17, // 年龄太小
email: "invalid".to_string(), // 无效邮箱
},
],
};
// 验证并打印所有错误
if let Err(errors) = invalid_business.validate() {
for error in errors {
println!("Validation error in field '{}': {}", error.field, error.message);
}
}
}
特性
- 类型安全验证:通过Rust的类型系统确保数据结构的正确性
- 丰富的验证规则:包括长度、范围、格式等多种验证条件
- 自定义验证:支持开发者定义自己的验证逻辑
- 高效编译时检查:宏在编译时展开,减少运行时开销
- 嵌套验证:支持验证嵌套的结构体和集合类型
许可证
本项目采用双许可证:
- MIT
- Apache-2.0
1 回复
以下是基于您提供的内容整理的完整示例demo,展示了near-schema-checker-macro库的各种用法:
基础用法示例
use near_schema_checker_macro::schema;
use serde_json::json;
// 1. 定义基本Schema
#[schema]
struct User {
id: u64,
username: String,
email: String,
age: Option<u8>,
is_active: bool,
}
fn basic_usage() {
// 2. 数据验证
let user_data = json!({
"id": 123,
"username": "rustacean",
"email": "user@example.com",
"age": 30,
"is_active": true
}).to_string();
let user: User = near_schema_checker_macro::from_str(&user_data).unwrap();
println!("Validated user: {:?}", user);
}
嵌套结构和高级验证示例
// 3. 嵌套结构验证
#[schema]
struct Post {
id: u64,
title: String,
content: String,
author: User, // 嵌套使用User结构
tags: Vec<String>,
}
// 4. 自定义验证规则
#[schema]
struct Product {
#[schema(min = 0.01)] // 价格最小0.01
price: f64,
#[schema(max_length = 100)] // 名称最大长度100
name: String,
#[schema(regex = "^[A-Z]{2}\\d{4}$")] // SKU格式要求
sku: String,
}
fn advanced_usage() {
let post_data = json!({
"id": 1,
"title": "Rust Schema Validation",
"content": "This is a post...",
"author": {
"id": 123,
"username": "rustacean",
"email": "user@example.com",
"is_active": true
},
"tags": ["rust", "macro"]
}).to_string();
let post: Post = near_schema_checker_macro::from_str(&post_data).unwrap();
println!("Validated post: {:?}", post);
}
枚举和集合验证示例
// 5. 枚举类型支持
#[schema]
enum AccountStatus {
Active,
Inactive,
Suspended,
}
#[schema]
struct Account {
id: u64,
status: AccountStatus,
last_login: Option<String>,
}
// 6. 集合验证
#[schema]
struct Order {
id: u64,
#[schema(min_items = 1)] // 至少1个订单项
items: Vec<String>,
#[schema(unique_items = true)] // 标签必须唯一
tags: Vec<String>,
}
fn enum_and_collections() {
let account_data = json!({
"id": 1,
"status": "Active",
"last_login": "2023-01-01"
}).to_string();
let account: Account = near_schema_checker_macro::from_str(&account_data).unwrap();
println!("Validated account: {:?}", account);
}
完整Web应用示例
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use near_schema_checker_macro::schema;
#[schema]
struct RegisterRequest {
username: String,
#[schema(min_length = 8)]
password: String,
#[schema(email)]
email: String,
}
async fn register(user: web::Json<RegisterRequest>) -> impl Responder {
// 数据已经通过Schema验证
HttpResponse::Ok().json("Registration successful")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::resource("/register")
.route(web::post().to(register))
)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
性能优化示例
use std::fs::File;
use once_cell::sync::Lazy;
#[schema]
struct Config {
#[schema(default = "localhost")]
host: String,
#[schema(default = 8080)]
port: u16,
}
// 重用已解析的Schema验证器
static CONFIG_VALIDATOR: Lazy<Config> = Lazy::new(|| {
let file = File::open("config.json").unwrap();
near_schema_checker_macro::from_reader(file).unwrap()
});
fn get_config() -> &'static Config {
&CONFIG_VALIDATOR
}
错误处理示例
fn handle_errors() {
let invalid_data = r#"
{
"id": "not_a_number", // 错误的类型
"username": "user",
"email": "invalid-email",
"is_active": true
}
"#;
match near_schema_checker_macro::from_str::<User>(invalid_data) {
Ok(user) => println!("Valid user: {:?}", user),
Err(e) => {
println!("Validation failed:");
println!("- Field: {}", e.field());
println!("- Error: {}", e.message());
println!("- Expected: {}", e.expected());
}
}
}
这些示例完整展示了near-schema-checker-macro库的主要功能,包括基础数据结构验证、嵌套结构、自定义验证规则、枚举支持、集合验证以及在Web应用和配置文件中的实际应用场景。