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

如何将SurrealDB Response转为User结构体并在Rocket端点返回用户JSON

解决方案

你需要对SurrealDB返回的Response进行逐层解析,提取用户对象后构造目标JSON返回。以下是修改后的完整接口代码:

#[post("/", data="<user>")]
pub async fn create_user(user: Json<User>, db: &State<Database>) -> Custom<Value> {
    println!("Creating a new user");

    // 执行插入查询(建议使用参数化查询避免SQL注入,优化写法见下文)
    let db_res = db.query(format!("INSERT INTO users (name, email, password) VALUES ('{}', '{}', '{}')", user.name, user.email, user.password)).await;

    match db_res {
        Ok(response) => {
            // 从results中取出插入操作的结果(对应key为0的条目)
            if let Some((_, Ok(Array(user_array)))) = response.results.get(&0) {
                // 插入单条数据时,返回数组中仅包含一个用户对象
                if let Some(Object(user_obj)) = user_array.first() {
                    // 提取并转换SurrealDB特定类型的字段
                    let user_id = match user_obj.get("id") {
                        Some(Thing(thing)) => thing.id.clone(), // 仅返回ID字符串,若需完整格式可写`format!("{}:{}", thing.tb, thing.id)`
                        _ => return Custom(Status::InternalServerError, json!({"status": "error", "message": "提取用户ID失败"})),
                    };
                    let user_name = match user_obj.get("name") {
                        Some(Strand(strand)) => strand.0.clone(),
                        _ => return Custom(Status::InternalServerError, json!({"status": "error", "message": "提取用户名失败"})),
                    };
                    let user_email = match user_obj.get("email") {
                        Some(Strand(strand)) => strand.0.clone(),
                        _ => return Custom(Status::InternalServerError, json!({"status": "error", "message": "提取用户邮箱失败"})),
                    };

                    // 构造目标格式的用户JSON
                    let new_user = json!({
                        "id": user_id,
                        "name": user_name,
                        "email": user_email
                    });

                    let final_response = json!({
                        "status": "success",
                        "message": "用户创建成功",
                        "data": new_user
                    });

                    return Custom(Status::Created, final_response);
                }
            }

            // 结果解析失败时返回错误
            Custom(Status::InternalServerError, json!({"status": "error", "message": "解析数据库返回的用户数据失败"}))
        }
        Err(e) => {
            // 处理数据库查询异常
            println!("数据库错误: {:?}", e);
            Custom(Status::InternalServerError, json!({"status": "error", "message": "数据库操作失败"}))
        }
    }
}

核心解析逻辑说明

  1. 处理Result包装:通过match分支处理数据库查询的成功/失败结果,避免程序panic。
  2. 定位结果集:SurrealDB的Response.results是HashMap结构,插入操作的结果对应key为0的条目。
  3. 解析用户数组:插入单条数据时,返回的是包含单个用户对象的Array,用first()取出目标对象。
  4. 转换SurrealDB类型:
    • Thing类型对应用户ID,可按需返回纯ID字符串或表名:ID的完整格式;
    • Strand类型是SurrealDB的字符串封装,通过.0获取内部原始字符串。

重要优化建议

你当前用format!拼接SQL存在SQL注入风险,建议改用参数化查询写法:

let db_res = db.query("INSERT INTO users (name, email, password) VALUES ($name, $email, $password)")
    .bind(("name", &user.name))
    .bind(("email", &user.email))
    .bind(("password", &user.password))
    .await;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 21:22:14