使用sqlx查询PostgreSQL JSONB列至含Json<_>字段的结构体失败
问题:sqlx查询PostgreSQL JSONB字段编译失败
环境与代码
PostgreSQL表定义
CREATE TABLE families ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), title VARCHAR(255) NOT NULL, entity_form JSONB NOT NULL, comment_form JSONB NOT NULL );
Rust结构体定义
#[derive(FromRow, Deserialize, Serialize, Debug)] pub struct Family { pub id: Uuid, pub title: String, pub entity_form: Json<Form>, pub comment_form: Json<Form>, } #[derive(Serialize, Deserialize, Debug)] pub struct Form { // ... fields ... }
查询代码
pub async fn get(given_id: Uuid, conn: &mut PgConnection) -> Result<Family, AppError> { sqlx::query_as!( Family, r#" SELECT id, title, entity_form, comment_form FROM families WHERE id = $1 "#, given_id ) .fetch_one(conn) .await .map_err(AppError::DatabaseError) }
编译报错
error[E0277]: the trait bound `sqlx::types::Json<family::Form>: From<JsonValue>` is not satisfied --> src/models/family.rs:181:9 | 181 | / sqlx::query_as!( 182 | | Family, 183 | | r#" 184 | | SELECT id, title, entity_form, comment_form ... | 188 | | given_id 189 | | ) | |_________^ the trait `From<JsonValue>` is not implemented for `sqlx::types::Json<family::Form>` |
已排查项:
- 移除
entity_form和comment_form字段后,查询可正常编译 - 已开启sqlx的
json特性 - 已开启serde_json的
raw_value特性
原因与解决方案
原因
sqlx::query_as!宏处理JSONB字段时,默认会将数据库返回的JSONB解析为serde_json::Value(即报错中的JsonValue),但你的结构体字段类型是sqlx::types::Json<Form>,而该类型未实现从JsonValue转换的From trait,导致类型不匹配。
解决方案
有两种可行的解决方式:
方式1:修改结构体字段类型
如果不需要sqlx::types::Json包裹,直接将字段类型改为Form(你已为Form添加Deserialize派生宏,满足反序列化要求):
#[derive(FromRow, Deserialize, Serialize, Debug)] pub struct Family { pub id: Uuid, pub title: String, pub entity_form: Form, pub comment_form: Form, }
这种情况下sqlx::query_as!会自动完成JSONB到Form的反序列化,无需额外处理。
方式2:在查询SQL中显式指定类型转换
若必须保留sqlx::types::Json<Form>类型,可在查询语句中为JSONB字段添加类型注解,明确告知宏解析规则:
pub async fn get(given_id: Uuid, conn: &mut PgConnection) -> Result<Family, AppError> { sqlx::query_as!( Family, r#" SELECT id, title, entity_form AS "entity_form: Json<Form>", comment_form AS "comment_form: Json<Form>" FROM families WHERE id = $1 "#, given_id ) .fetch_one(conn) .await .map_err(AppError::DatabaseError) }
通过AS "字段名: 目标类型"的语法,让宏明确将entity_form和comment_form解析为Json<Form>类型,匹配结构体字段类型后即可解决编译错误。
内容的提问来源于stack exchange,提问作者élysé
相关产品推荐
相关产品推荐

