MongoDB Rust驱动无法使用u128数据类型的问题求助
在MongoDB Rust驱动中使用u128数据类型的解决方案
问题描述
尝试在MongoDB Rust驱动中使用u128类型作为文档字段时,遇到BSON序列化错误:u128 is not supported。以下是报错的示例代码:
use mongodb::{bson::{doc}, options::{ClientOptions, ServerApi, ServerApiVersion}, Client}; use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize)] struct Book { id : u128, title : String, author: String, } #[tokio::main] async fn main() -> mongodb::error::Result<()> { // 创建客户端配置 let uri = "mongodb://localhost:27017"; let mut client_options = ClientOptions::parse(uri).await?; // 设置Server API let server_api = ServerApi::builder().version(ServerApiVersion::V1).build(); client_options.server_api = Some(server_api); client_options.app_name = Some("Books".to_string()); // 创建客户端并连接服务器 let client = Client::with_options(client_options)?; // 获取数据库句柄 let db = client.database("books"); // 获取强类型集合句柄 let collection = db.collection::<Book>("books"); let books = vec![ Book { id: u128::pow(2,64), title: "The Grapes of Wrath".to_string(), author: "John Steinbeck".to_string(), }, Book { id: u128::pow(2,64)+1, title: "To Kill a Mockingbird".to_string(), author: "Harper Lee".to_string(), }, ]; // 插入文档 collection.insert_many(books, None).await?; Ok(()) }
运行时错误信息:
Compiling mongodb_dr v0.1.0 (/Users/username/repo/git/rustwerk/mongodb_dr) Finished dev [unoptimized + debuginfo] target(s) in 0.84s Running `target/debug/mongodb_dr` Error: Error { kind: BsonSerialization(SerializationError { message: "u128 is not supported" }), labels: {}, wire_version: Some(17), source: None }
解决方法
BSON原生不支持u128类型,需要通过自定义Serde序列化/反序列化逻辑,将u128转换为BSON支持的类型(如String或Decimal128)。
方案1:将u128序列化为字符串
通过Serde的with属性自定义转换逻辑,把u128转成字符串存储,读取时再转换回u128,适合仅作为标识、无需数值运算的场景:
use mongodb::{bson::{doc}, options::{ClientOptions, ServerApi, ServerApiVersion}, Client}; use serde::{Deserialize, Serialize, Deserializer, Serializer}; // 自定义u128转字符串的序列化函数 fn serialize_u128<S>(value: &u128, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { serializer.serialize_str(&value.to_string()) } // 自定义字符串转u128的反序列化函数 fn deserialize_u128<'de, D>(deserializer: D) -> Result<u128, D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; s.parse().map_err(serde::de::Error::custom) } #[derive(Debug, Deserialize, Serialize)] struct Book { #[serde(serialize_with = "serialize_u128", deserialize_with = "deserialize_u128")] id : u128, title : String, author: String, } #[tokio::main] async fn main() -> mongodb::error::Result<()> { let uri = "mongodb://localhost:27017"; let mut client_options = ClientOptions::parse(uri).await?; let server_api = ServerApi::builder().version(ServerApiVersion::V1).build(); client_options.server_api = Some(server_api); client_options.app_name = Some("Books".to_string()); let client = Client::with_options(client_options)?; let db = client.database("books"); let collection = db.collection::<Book>("books"); let books = vec![ Book { id: u128::pow(2,64), title: "The Grapes of Wrath".to_string(), author: "John Steinbeck".to_string(), }, Book { id: u128::pow(2,64)+1, title: "To Kill a Mockingbird".to_string(), author: "Harper Lee".to_string(), }, ]; collection.insert_many(books, None).await?; Ok(()) }
方案2:将u128转换为Decimal128
MongoDB支持Decimal128类型,可以直接存储大整数,适合需要数值运算的场景:
use mongodb::{bson::{doc, Decimal128}, options::{ClientOptions, ServerApi, ServerApiVersion}, Client}; use serde::{Deserialize, Serialize, Deserializer, Serializer}; use std::str::FromStr; // 自定义u128转Decimal128的序列化函数 fn serialize_u128_to_decimal<S>(value: &u128, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { let decimal = Decimal128::from_str(&value.to_string()) .map_err(serde::ser::Error::custom)?; serializer.serialize_newtype_struct("Decimal128", &decimal) } // 自定义Decimal128转u128的反序列化函数 fn deserialize_decimal_to_u128<'de, D>(deserializer: D) -> Result<u128, D::Error> where D: Deserializer<'de>, { let decimal = Decimal128::deserialize(deserializer)?; decimal.to_string().parse().map_err(serde::de::Error::custom) } #[derive(Debug, Deserialize, Serialize)] struct Book { #[serde(serialize_with = "serialize_u128_to_decimal", deserialize_with = "deserialize_decimal_to_u128")] id : u128, title : String, author: String, } #[tokio::main] async fn main() -> mongodb::error::Result<()> { let uri = "mongodb://localhost:27017"; let mut client_options = ClientOptions::parse(uri).await?; let server_api = ServerApi::builder().version(ServerApiVersion::V1).build(); client_options.server_api = Some(server_api); client_options.app_name = Some("Books".to_string()); let client = Client::with_options(client_options)?; let db = client.database("books"); let collection = db.collection::<Book>("books"); let books = vec![ Book { id: u128::pow(2,64), title: "The Grapes of Wrath".to_string(), author: "John Steinbeck".to_string(), }, Book { id: u128::pow(2,64)+1, title: "To Kill a Mockingbird".to_string(), author: "Harper Lee".to_string(), }, ]; collection.insert_many(books, None).await?; Ok(()) }
注意事项
- 使用字符串存储时,无法直接在MongoDB中对该字段进行数值运算。
- 使用Decimal128存储时,需确保MongoDB版本为3.4及以上,该版本开始支持Decimal128类型。
内容的提问来源于stack exchange,提问作者mabalenk
相关产品推荐
相关产品推荐

