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

如何控制serde_json序列化结构体行为,实现Uuid与base62自动互转?

解决方案

1. 先添加必要依赖

在Cargo.toml中加入以下依赖,版本可根据项目实际情况调整:

[dependencies]
uuid = { version = "1.0", features = ["serde", "v4", "sqlx"] }
serde = { version = "1.0", features = ["derive"] }
base62 = "2.0"
sqlx = { version = "0.5", features = ["postgres", "runtime-tokio-native-tls", "uuid"] }

2. 实现Uuid和Base62互转的serde自定义逻辑

封装独立的序列化/反序列化模块,不会修改字段本身的Uuid类型,完全不影响sqlx的类型映射逻辑:

use serde::{Deserialize, Deserializer, Serializer};
use uuid::Uuid;

pub mod uuid_base62 {
    use super::*;

    /// 将Uuid序列化为base62编码字符串
    pub fn serialize<S>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let bytes = uuid.as_u128();
        let base62_str = base62::encode(bytes);
        serializer.serialize_str(&base62_str)
    }

    /// 将base62编码字符串反序列化为Uuid
    pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        let num = base62::decode(&s).map_err(serde::de::Error::custom)?;
        Ok(Uuid::from_u128(num))
    }
}

3. 给结构体字段添加serde属性

只需要在id字段上标注使用自定义转换逻辑即可,原有FromRow推导、query_as!调用方式完全不需要改动:

#[derive(Debug, Deserialize, sqlx::FromRow, Serialize)]
pub struct Widget {
    #[serde(with = "uuid_base62")]
    pub id: Uuid,
    pub name: String,
}

效果验证

  • 数据库查询逻辑完全不变:let widget = query_as!(Widget, r#"select * from widgets where id = $1"#, id).fetch_one(db_conn).await?; 可以正常执行,sqlx能正确把数据库返回的uuid类型映射到结构体的Uuid字段
  • 序列化响应给客户端时,id字段会自动转为base62编码的字符串,比如"id": "7N3WXf8qZt2"格式
  • 接收客户端请求时,传入的base62字符串会自动转成Uuid类型,不需要手动处理转换逻辑

如果多个结构体都需要这个转换能力,把uuid_base62模块抽到公共位置即可,所有需要转base62的Uuid字段都可以加#[serde(with = "uuid_base62")]复用,不需要重复写转换代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:48:00