Diesel 2无法反序列化Uuid的编译错误排查求助
Diesel查询PostgreSQL时的FromStaticSqlRow trait绑定错误
问题场景
使用Actix Web结合Diesel操作PostgreSQL数据库时,编写用户查询接口出现编译错误,相关代码及错误信息如下:
接口代码
pub async fn get( user_uuid: web::Path<uuid::Uuid>, data: web::Data<AppState>, ) -> Result<impl Responder, actix_web::Error> { use crate::schema::users::dsl::*; let mut conn = get_conn(&data.pool).await?; use uuid::Uuid; let user_id = user_uuid.into_inner(); let result: Result<User, diesel::result::Error> = users.find(user_id).first(&mut conn); }
依赖配置
diesel = {version = "2.1.3", features = ["postgres", "chrono", "r2d2", "uuid", "serde_json"]} uuid = { version = "1.4.1", features = ["serde", "v4"] }
User模型
#[allow(non_snake_case)] #[derive(Debug, Insertable, Queryable, AsChangeset, Serialize, Deserialize, Clone)] pub struct User { pub id: uuid::Uuid, pub name: String, pub email: String, pub password: String, pub is_admin: bool, #[serde(rename = "createdAt")] pub created_at: Option<NaiveDateTime>, #[serde(rename = "updatedAt")] pub updated_at: Option<NaiveDateTime>, }
schema.rs定义
diesel::table! { users (id) { id -> Uuid, #[max_length = 100] name -> Varchar, #[max_length = 255] email -> Varchar, is_admin -> Bool, #[max_length = 100] password -> Varchar, created_at -> Nullable<Timestamptz>, updated_at -> Nullable<Timestamptz>, } }
编译错误信息
server % cargo check Checking server v0.1.0 error[E0277]: the trait bound `(uuid::Uuid, std::string::String, std::string::String, std::string::String, bool, std::option::Option<NaiveDateTime>, std::option::Option<NaiveDateTime>): FromStaticSqlRow<(diesel::sql_types::Uuid, Text, Text, diesel::sql_types::Bool, Text, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), Pg>` is not satisfied --> src/routes/user.rs:44:85 | 44 | let result: Result<User, diesel::result::Error> = users.find(user_id).first(&mut conn); | ----- ^^^^^^^^^ the trait `FromStaticSqlRow<(diesel::sql_types::Uuid, Text, Text, diesel::sql_types::Bool, Text, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>, diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>), Pg>` is not implemented for `(uuid::Uuid, std::string::String, std::string::String, std::string::String, bool, std::option::Option<NaiveDateTime>, std::option::Option<NaiveDateTime>)` | | | required by a bound introduced by this call | = help: the following other types implement trait `FromStaticSqlRow<ST, DB>`: <(T0,) as FromStaticSqlRow<(ST0,), __DB>> <(T1, T0) as FromStaticSqlRow<(ST1, ST0), __DB>> <(T1, T2, T0) as FromStaticSqlRow<(ST1, ST2, ST0), __DB>> <(T1, T2, T3, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST0), __DB>> <(T1, T2, T3, T4, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST0), __DB>> <(T1, T2, T3, T4, T5, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST0), __DB>> <(T1, T2, T3, T4, T5, T6, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST0), __DB>> <(T1, T2, T3, T4, T5, T6, T7, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST0), __DB>>
错误原因
核心问题是User结构体的字段顺序与schema.rs中定义的数据库表字段顺序不匹配。
Diesel的Queryable trait要求结构体字段顺序必须和数据库表(schema.rs)的字段顺序完全一致,否则在反序列化查询结果时,类型映射会出现错位,导致编译器抛出FromStaticSqlRow trait未实现的错误。
对比两者的字段顺序:
- schema.rs中users表字段顺序:
id→name→email→is_admin→password→created_at→updated_at - User结构体字段顺序:
id→name→email→password→is_admin→created_at→updated_at
可以看到password和is_admin的顺序在结构体和schema中颠倒,导致Diesel无法正确映射字段类型。
解决方法
调整User结构体的字段顺序,使其与schema.rs中定义的表字段顺序完全一致:
修改后的User模型代码:
#[allow(non_snake_case)] #[derive(Debug, Insertable, Queryable, AsChangeset, Serialize, Deserialize, Clone)] pub struct User { pub id: uuid::Uuid, pub name: String, pub email: String, pub is_admin: bool, // 将is_admin移至password之前,与schema顺序对齐 pub password: String, #[serde(rename = "createdAt")] pub created_at: Option<NaiveDateTime>, #[serde(rename = "updatedAt")] pub updated_at: Option<NaiveDateTime>, }
修改完成后重新执行cargo check或cargo build,错误即可消除。
额外提示:
- 后续修改schema或结构体时,务必保持两者的字段顺序一致
- 若不想依赖字段顺序,可使用Diesel的
#[diesel(column_name = "...")]属性显式指定字段映射,但对于简单场景,保持顺序一致更直观
内容的提问来源于stack exchange,提问作者Nikita Prokaiev
相关产品推荐
相关产品推荐

