如何在Rust中自动计算ArticleModel的read_time_in_min与word_count字段
解决方案
最稳妥的方式是拆分请求结构体和业务结构体,明确区分前端需要提交的字段和后端自动计算的字段,避免反序列化冲突。
方法一:拆分结构体(推荐)
- 定义仅包含前端需提交字段的请求结构体,用于反序列化请求体
- 定义包含所有字段的业务结构体,用于后续业务逻辑
- 通过
Fromtrait实现从请求结构体到业务结构体的转换,在转换过程中自动计算目标字段
代码示例(以Rust Axum框架为例)
use serde::Deserialize; use axum::{extract::Json, response::IntoResponse}; // 前端请求结构体:仅包含用户需要提交的字段 #[derive(Deserialize)] struct ArticleRequest { title: String, text: String, // 其他前端可提交的字段,比如category等 } // 业务逻辑结构体:包含所有字段(含自动计算的字段) #[derive(Debug)] struct ArticleModel { title: String, text: String, word_count: usize, read_time_in_min: f32, // 其他业务字段 } // 实现从请求结构体到业务结构体的转换 impl From<ArticleRequest> for ArticleModel { fn from(req: ArticleRequest) -> Self { // 计算词数:这里用简单的空格分割,实际可根据需求优化(比如排除标点) let word_count = req.text.split_whitespace().count(); // 计算阅读时间:按行业通用的每分钟200词估算 let read_time_in_min = word_count as f32 / 200.0; ArticleModel { title: req.title, text: req.text, word_count, read_time_in_min, } } } // API处理函数 async fn create_article(Json(req): Json<ArticleRequest>) -> impl IntoResponse { // 将请求转换为业务模型 let article = ArticleModel::from(req); // 后续逻辑:比如存入数据库、返回响应等 Ok(Json(article)) }
这种方式的优势在于:
- 前端明确知道哪些字段需要提交,避免传参混淆
- 反序列化过程不会报错,因为请求结构体不包含自动计算的字段
- 业务逻辑和请求解耦,代码更清晰
方法二:单结构体配合默认值与验证
如果不想拆分结构体,可以通过serde的默认值属性让字段允许缺省,然后在反序列化后覆盖计算值,同时验证前端是否违规传入了自动计算的字段。
代码示例
use serde::Deserialize; use axum::{extract::Json, response::IntoResponse, http::StatusCode}; #[derive(Deserialize, Debug)] struct ArticleModel { title: String, text: String, // 设为默认值0,前端不传时自动填充 #[serde(default)] word_count: usize, // 设为默认值0.0 #[serde(default)] read_time_in_min: f32, } async fn create_article(mut Json(mut article): Json<ArticleModel>) -> Result<impl IntoResponse, StatusCode> { // 验证前端是否传入了自动计算的字段,若传入则返回错误 if article.word_count != 0 || article.read_time_in_min != 0.0 { return Err(StatusCode::BAD_REQUEST); } // 计算并覆盖字段值 article.word_count = article.text.split_whitespace().count(); article.read_time_in_min = article.word_count as f32 / 200.0; // 后续业务逻辑 Ok(Json(article)) }
为什么new方法无效?
你遇到的JSON解析错误,是因为serde在反序列化时会严格匹配结构体的所有字段(除非字段标记为可选或有默认值)。如果结构体包含word_count和read_time_in_min,但前端没有传入,serde会因缺少必填字段而抛出错误。而new方法是手动创建结构体的方式,serde反序列化过程不会主动调用它,因此无法解决问题。
内容的提问来源于stack exchange,提问作者Matthew Trent
相关产品推荐
相关产品推荐

