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

如何让Axum Handler函数返回Vec<String>?

Axum + SQLx 查询全量数据编译错误解决

问题背景

基于Axum的sqlx-postgres示例开发,数据库表结构如下:

todo  | description
--------+--------------
 todo_1 | doing todo 1
 todo_2 | doing todo 2
 todo_3 | doing todo 3

尝试修改using_connection_pool_extractor函数,通过SELECT * FROM todos获取全量数据,返回Result<Vec<String>, (StatusCode, String)>时触发编译错误。

出错代码

async fn using_connection_pool_extractor(
    Extension(pool): Extension<PgPool>,
) -> Result<Vec<String>, (StatusCode, String)> {
    sqlx::query_scalar("select * from todos")
        .fetch_one(&pool)
        .await
        .map_err(internal_error)
}

错误信息

error[E0277]: the trait bound `fn(Extension<Pool<sqlx::Postgres>>) -> impl Future<Output = Result<Vec<String>, (StatusCode, String)>> {using_connection_pool_extractor}: Handler<_, _>` is not satisfied
   --> src/main.rs:52:17
    |
52  |             get(using_connection_pool_extractor).post(using_connection_extractor),
    |             --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(Extension<Pool<sqlx::Postgres>>) -> impl Future<Output = Result<Vec<String>, (StatusCode, String)>> {using_connection_pool_extractor}`
    |             |
    |             required by a bound introduced by this call
    |
    = help: the trait `Handler<T, ReqBody>` is implemented for `axum::handler::Layered<S, T>`
note: required by a bound in `axum::routing::get`

问题原因与解决方法

核心问题

  1. 查询方法与语句不匹配:fetch_one仅返回单条数据,无法获取全量;query_scalar用于查询单列数据,但SELECT *返回多列,类型不匹配导致后续类型推导错误,最终触发Handler trait不满足的报错。
  2. 返回类型定义错误:表包含两列,SELECT *返回的是完整行数据,不是String类型,更无法直接转为Vec<String>。

修复步骤

1. 定义表对应的数据结构

先创建结构体映射数据库行,需启用serde的derive特性用于JSON序列化:

use serde::Serialize;

#[derive(Debug, Serialize, sqlx::FromRow)]
struct Todo {
    todo: String,
    description: String,
}

Cargo.toml需添加依赖:

serde = { version = "1.0", features = ["derive"] }

2. 修改查询与返回逻辑

使用query_as配合fetch_all获取全量数据,并用Json包裹返回值(Axum会自动处理响应序列化):

async fn using_connection_pool_extractor(
    Extension(pool): Extension<PgPool>,
) -> Result<Json<Vec<Todo>>, (StatusCode, String)> {
    let todos = sqlx::query_as::<_, Todo>("select * from todos")
        .fetch_all(&pool)
        .await
        .map_err(internal_error)?;

    Ok(Json(todos))
}

3. 简化场景(仅需单列数据)

如果只需要todo列的字符串列表,可修改查询语句:

async fn using_connection_pool_extractor(
    Extension(pool): Extension<PgPool>,
) -> Result<Json<Vec<String>>, (StatusCode, String)> {
    let todos = sqlx::query_scalar("select todo from todos")
        .fetch_all(&pool)
        .await
        .map_err(internal_error)?;

    Ok(Json(todos))
}

内容的提问来源于stack exchange,提问作者kinxiel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 09:18:25