类型转换(枚举/JSON/Decimal)
大约 2 分钟
类型转换(枚举/JSON/Decimal)
Sea-ORM 提供丰富的类型映射能力:枚举(ActiveEnum)、JSON、Decimal、数组(PostgreSQL)等。合理建模能提升类型安全与可读性。
枚举(ActiveEnum)
use sea_orm::entity::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, serde::Serialize, serde::Deserialize)]
#[sea_orm(rs_type = "String", db_type = "String(Some(20))")]
pub enum UserStatus {
#[sea_orm(string_value = "ENABLED")]
Enabled,
#[sea_orm(string_value = "DISABLED")]
Disabled,
}
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
pub status: UserStatus, // 强类型字段
}
rs_type
为 Rust 端类型,db_type
为数据库存储类型- 也可存为整数枚举(
rs_type = "i32", db_type = "Integer"
)
JSON 字段
- 使用
serde_json::Value
或强类型结构体(推荐)
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct Profile { pub phone: Option<String>, pub avatar: Option<String> }
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
#[sea_orm(column_type = "JsonBinary")] // PG jsonb / MySQL json
pub profile: Option<serde_json::Value>, // 或者:Option<Profile>(0.13+ 支持 typed json)
}
读写:
// 写入
let prof = Profile { phone: Some("1380000".into()), avatar: None };
am.profile = Set(Some(serde_json::to_value(prof)?));
// 读取为强类型
if let Some(v) = model.profile {
let p: Profile = serde_json::from_value(v)?;
}
Decimal(高精度数值)
- 使用
sea_orm::prelude::Decimal
(基于 bigdecimal)
use sea_orm::prelude::Decimal;
#[derive(DeriveEntityModel, Debug, Clone)]
pub struct Model {
pub price: Decimal, // 对应 decimal(18,2)
}
- 运算注意精度与四舍五入:
price.round_dp(2)
数组(PostgreSQL)
#[derive(DeriveEntityModel, Debug, Clone)]
pub struct Model {
#[sea_orm(column_type = "Array(String)")]
pub tags: Vec<String>,
}
查询包含:
use sea_orm::sea_query::Expr;
.filter(Expr::cust_with_values("tags @> ARRAY[?]::varchar[]", vec!["admin".into()]))
字段默认值与转换
- 默认值:在迁移中设置默认;或在
before_save
填充 - 自定义转换:对 VO 层做转换(例如分/元换算),数据库保持基础类型
小结
- ActiveEnum 提供强类型枚举映射
- JSON 字段尽量用强类型结构体(便于校验与演化)
- 金额/高精度用 Decimal,避免浮点误差
- PostgreSQL 支持数组/JSONB 强力查询,合理利用