如何将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": "数据库操作失败"})) } } }
核心解析逻辑说明
- 处理Result包装:通过
match分支处理数据库查询的成功/失败结果,避免程序panic。 - 定位结果集:SurrealDB的
Response.results是HashMap结构,插入操作的结果对应key为0的条目。 - 解析用户数组:插入单条数据时,返回的是包含单个用户对象的
Array,用first()取出目标对象。 - 转换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
相关产品推荐
相关产品推荐

