You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:31:25