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

Rust中是否存在类似Java MapStruct/Bean.copyProperties的实体自动映射方案?

Rust中是否存在类似Java MapStruct/Bean.copyProperties的实体自动映射方案?

看了你手动实现From trait的代码,确实当结构体字段多的时候,这种逐个字段赋值的写法会特别繁琐,Rust社区里其实有不少成熟的工具能帮你实现类似Java里MapStruct或者Bean.copyProperties的自动映射效果,不用再手动写重复的赋值代码。

给你分享几个实用的方案:

1. 用专门的结构体转换crate(推荐)

比如struct-convert这个 crate,它专门用来自动生成结构体之间的转换实现,能根据字段名自动匹配,还支持自定义个别字段的处理逻辑,完全能满足你的需求。

用法示例:

首先在你的Cargo.toml里添加依赖:

struct-convert = { version = "0.4", features = ["derive"] }

然后修改你的结构体代码,通过派生宏自动生成转换逻辑:

use serde::{Deserialize, Serialize};
use crate::model::diesel::tex::custom_tex_models::TexProject;
use struct_convert::Convert;

#[derive(Deserialize, Serialize, Convert)]
#[allow(non_snake_case)]
#[convert(from = "TexProject")]
#[convert_field(role_id = 0)] // 给特殊字段role_id指定默认值
pub struct TexProjResp {
    pub id: i64,
    pub proj_name: String,
    pub created_time: i64,
    pub updated_time: i64,
    pub proj_status: i32,
    pub template_id: i64,
    pub project_id: String,
    pub nickname: String,
    pub role_id: i32,
}

这样一来,crate会自动帮你生成和手动实现一样的From<&TexProject> for TexProjResp逻辑,大部分字段自动按名映射,个别特殊字段(比如这里的role_id)可以通过宏参数指定默认值,代码一下子就简洁了。

另外还有derive_more crate,它的From派生宏也能自动处理字段完全匹配的场景,如果有个别字段需要调整,你可以在派生后手动补全差异部分,也能省不少代码。

2. 借助serde的序列化反序列化(应急方案)

如果只是临时需求或者数据量不大,你也可以利用serde的序列化反序列化能力来做转换:把源结构体序列化成中间格式(比如JSON),再反序列化成目标结构体。不过这种方式有额外的性能开销,不太适合高性能场景,而且需要两个结构体都实现对应的serde trait。

示例代码大概是这样:

use serde::{Serialize, Deserialize};
use serde_json;

fn convert_proj(proj: &TexProject) -> TexProjResp {
    // 先序列化源结构体
    let json_str = serde_json::to_string(proj).unwrap();
    // 反序列化成目标结构体
    let mut resp: TexProjResp = serde_json::from_str(&json_str).unwrap();
    // 手动修正特殊字段
    resp.role_id = 0;
    resp
}

总结

如果追求简洁和性能,优先用专门的结构体转换crate,比如struct-convert,它完全能达到你想要的“一行代码搞定映射”的效果;如果是小场景应急,serde的方式也能凑合用。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:13:05