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

如何在Rust中自动计算ArticleModel的read_time_in_min与word_count字段

解决方案

最稳妥的方式是拆分请求结构体和业务结构体,明确区分前端需要提交的字段和后端自动计算的字段,避免反序列化冲突。

方法一:拆分结构体(推荐)

  1. 定义仅包含前端需提交字段的请求结构体,用于反序列化请求体
  2. 定义包含所有字段的业务结构体,用于后续业务逻辑
  3. 通过From trait实现从请求结构体到业务结构体的转换,在转换过程中自动计算目标字段

代码示例(以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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:35:26