如何为sqlx::query_as结果用自定义类型?遇FromRow trait约束不满足错误
解决Rust sqlx 0.7x中query_as反序列化自定义结构体的FromRow错误
你在使用sqlx 0.7x的query_as和fetch_all将SQLite查询结果转为Vec<Todo>时遇到了FromRow trait未实现的错误,核心原因是sqlx反序列化数据库查询结果依赖的是自身的FromRow trait,而非serde的Deserialize特性。
修复步骤
1. 为结构体派生sqlx的FromRow trait
修改结构体的derive属性,添加sqlx::FromRow,同时保留需要的serde特性:
use serde::{Deserialize, Serialize}; use sqlx::{FromRow, sqlite::SqlitePoolOptions}; #[derive(Serialize, Deserialize, FromRow)] struct Todo { id: String, completed: bool, }
2. 确保Cargo.toml启用正确的sqlx特性
sqlx的派生宏需要启用macros特性,同时要指定sqlite相关依赖特性,示例Cargo.toml配置:
[dependencies] sqlx = { version = "0.7", features = ["sqlite", "macros", "runtime-tokio-native-tls"] } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.0", features = ["full"] }
3. 验证字段与数据库列名匹配
确保Todo结构体的字段名、类型与todos表的列完全对应:
- 字段名需和列名一致(SQLite大小写不敏感,但严格匹配避免意外)
- 类型要对应:比如数据库中
id是文本类型,结构体用String;completed是布尔类型,结构体用bool
修正后的完整代码
use serde::{Deserialize, Serialize}; use sqlx::{FromRow, sqlite::SqlitePoolOptions}; #[derive(Serialize, Deserialize, FromRow)] struct Todo { id: String, completed: bool, } #[tokio::main] async fn main() { let pool = SqlitePoolOptions::new() .connect("sqlite:mydatabase.db") .await .expect("无法连接到数据库"); let todos: Vec<Todo> = sqlx::query_as::<_, Todo>("SELECT * FROM todos") .fetch_all(&pool) .await .unwrap(); }
内容的提问来源于stack exchange,提问作者Alexander Staroselsky
相关产品推荐
相关产品推荐

