如何让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`
问题原因与解决方法
核心问题
- 查询方法与语句不匹配:
fetch_one仅返回单条数据,无法获取全量;query_scalar用于查询单列数据,但SELECT *返回多列,类型不匹配导致后续类型推导错误,最终触发Handlertrait不满足的报错。 - 返回类型定义错误:表包含两列,
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
相关产品推荐
相关产品推荐

