Rust中Postgres NUMERIC与BigDecimal序列化映射问题求助
问题解决方案
核心问题分析
你遇到的矛盾是:
sqlx::types::BigDecimal实现了与PostgresNUMERIC类型交互的sqlx::Type<Postgres>trait,但默认未开启serde支持,无法反序列化请求数据- 单独的
bigdecimalcrate 开启serde特性后可支持反序列化,但未实现sqlx::Type<Postgres>,无法与数据库交互
只需通过配置sqlx的特性,就能让它提供的BigDecimal同时满足两种需求。
步骤1:修改Cargo.toml配置
删除单独的bigdecimal依赖,给sqlx添加serde特性,让sqlx封装的BigDecimal支持serde序列化/反序列化:
[dependencies] secrecy = { version = "0.8", features = ["serde"] } actix-web = "4.3.1" serde = { version = "1", features = ["derive"]} tokio = { version = "1", features = ["macros", "rt-multi-thread"] } uuid = { version = "1.3.4", features = ["v4"] } config = "0.11" chrono = { version = "0.4.26", features = ["serde"] } [dependencies.sqlx] version = "0.6.3" default-features = false features = [ "runtime-actix-rustls", "macros", "postgres", "uuid", "chrono", "migrate", "bigdecimal", "serde" # 新增该特性,让sqlx的BigDecimal支持serde ]
步骤2:调整Book结构体的导入
换回sqlx提供的BigDecimal,移除单独的bigdecimal crate导入:
use chrono::{DateTime, Utc}; use chrono::serde::ts_seconds; use sqlx::types::BigDecimal; // 使用sqlx封装的BigDecimal #[derive(serde::Deserialize)] pub struct Book { pub author: String, pub title: String, pub pages: i32, pub price: BigDecimal, #[serde(with = "ts_seconds")] pub published_at: DateTime<Utc> }
步骤3:验证插入函数
插入函数无需修改,sqlx的BigDecimal已经实现了与Postgres的类型映射,可以直接传入sqlx::query!宏:
pub async fn insert_book(data: &Book, pool: &PgPool) -> Result<(), sqlx::Error> { sqlx::query!( r#" INSERT INTO books (id, author, title, pages, price, published_at) VALUES ($1, $2, $3, $4, $5, $6) "#, Uuid::new_v4(), data.author, data.title, data.pages, data.price, data.published_at ) .execute(pool) .await?; Ok(()) }
额外说明
如果后续需要将Book结构体序列化为JSON返回给客户端,只需给结构体添加serde::Serialize派生即可:
#[derive(serde::Deserialize, serde::Serialize)] pub struct Book { // 字段保持不变 }
内容的提问来源于stack exchange,提问作者Sharmiko
相关产品推荐
相关产品推荐

