rust学习-json的序列化和反序列化

这篇博客介绍了如何在Rust中使用Serde库进行JSON序列化和反序列化,涵盖了序列化键、值、Option、枚举、Map、原子变量、BTreeMap、BTreeSet和BinaryHeap等内容。Serde还支持多种数据格式,如CBOR、YAML等。博客特别强调了BinaryHeap的序列化挑战,因为它涉及所有权和借用关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于 serde 库默认使用 JSON 格式进行序列化和反序列化
因此程序将使用 JSON 格式对数据进行序列化和反序列化

社区为 Serde 实现的部分数据格式列表:

  • JSON:广泛使用的 JavaScript 对象符号,用于许多 HTTP API
  • Postcard:no_std 和嵌入式系统友好的紧凑二进制格式。
  • CBOR:用于小消息大小且无需版本协商的简洁二进制对象表示法。
  • YAML:自称为“人类友好”的配置语言(不是标记语言)。
  • MessagePack:类似于紧凑 JSON 的高效二进制格式。
  • TOML:Cargo 使用的最小配置格式。
  • Pickle:Python 世界中常见的格式。
  • RON:一种 Rust 对象表示法。
  • BSON:MongoDB 使用的数据存储和网络传输格式。
  • Avro:用于 Apache Hadoop 内部的二进制格式,支持模式定义。
  • JSON5:包括 ES5 中的某些生成的 JSON 超集。
  • URL 查询字符串,x-www-form-urlencoded 格式。
  • Starlark:由 Bazel 和 Buck 构建系统用于描述构建目标的格式。(仅序列化)
  • Envy:将环境变量反序列化为 Rust 结构的一种方式。(仅反序列化)
  • Envy Store:将 AWS Parameter Store 参数反序列化为 Rust 结构的一种方式。(仅反序列化)
  • S-表达式:Lisp 语言系列使用的代码和数据的文本表示形式。
  • D-Bus 的二进制线格式。
  • FlexBuffers:Google 的 FlatBuffers 无拷贝序列化格式的无模式表兄弟。
  • Bencode:BitTorrent 协议中使用的简单二进制格式。
  • Token 流,用于处理 Rust 过程宏输入。(仅反序列化)
  • DynamoDB 项:rusoto_dynamodb 用于与 DynamoDB 传输数据的格式。
  • Hjson:围绕人类阅读和编辑而设计的 JSON 语法扩展。(仅反序列化)

serde学习

use serde::{
   Serialize, Deserialize};

// `derive` may only be applied to `struct`s, `enum`s and `union`s
#[derive(Serialize, Deserialize, Debug)]
struct Animal {
   
    name: String,
    age: u32,
}

fn main() {
   
	let animal = Animal {
   
		name: "Dog".to_owned(),
		age: 1,
	};
	let json_str = serde_json::to_string(&animal).unwrap();
	println!("{}", json_str);

	let json_str1 = r#"{"name":"Dog","age":1}"#;

	// 编译器无法推断变量或函数的类型,并需要使用类型注解来明确指定类型
	let animal1: Animal = serde_json::from_str(json_str1).unwrap();
	println!("{:?}", animal1)
}

更新序列化的键

use serde::{
   Serialize, Deserialize, Serializer, Deserializer};

#[derive(Serialize, Deserialize, Debug)]
struct Animal {
   
    #[serde(rename = "animal_name")]
	NaMe: String,
    #[serde(rename = "animal_age")]
    AgE: u32,
}

fn main() {
   
	let animal = Animal {
   
		NaMe: "Dog".to_owned(),
		AgE: 1,
	};

	let json_str = serde_json::to_string(&animal).unwrap();
	println!("{}", json_str);

	let json_str1 = r#"{"animal_name":"Dog","animal_age":1}"#;

	// 编译器无法推断变量或函数的类型,并需要使用类型注解来明确指定类型
	let animal1: Animal = serde_json::from_str(json_str1).unwrap();
	println!("{:?}", animal1)
}

打印内容如下

{
   "animal_name":"DOG","animal_age":1}
Animal {
    NaMe: "dog", AgE: 1 }

更新序列化的值

该场景在业务中貌似不会用到!!!

use serde::{
   Serialize, Deserialize, Serializer, Deserializer};

#[derive(Serialize, Deserialize, Debug)]
struct Animal {
   
    #[serde(serialize_with = "serialize_name", deserialize_with = "deserialize_name")]
    // 上述serde仅处理Nme
    NaMe: String,
    AgE: u32,
}

// 使用 serde 库自定义的序列化和反序列化函数
// 在序列化和反序列化期间自定义字段的名称,并使用自定义的名称序列化和反序列化数据
fn serialize_name<S>(name: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
   
	// 将输入字符串转换为大写并序列化
    serializer.serialize_str(&name.to_uppercase())
}

fn deserialize_name<'de, D>(deserializer: D) -> Result<String, D::Error>
where
    D: Deserializer<'de>,
{
   
    let name = String::deserialize(deserializer)?;
    // 获取输入字符串 name,并使用 name.to_lowercase() 将其转换为小写形式
	Ok(name.to_lowercase())
}

fn main() {
   
	let animal = Animal {
   
		
<think>好的,我现在需要为用户介绍Rust中的rkyv序列化反序列化。首先,我应该回忆一下rkyv的基本概念它在Rust生态系统中的地位。rkyv是一个零拷贝反序列化框架,主要特点是高性能内存安全,这应该是它的主要卖点。我需要确保这些点被明确传达。 接下来,我需要考虑用户可能的背景。他们可能已经了解一些序列化库,比如serde,但想了解rkyv的不同之处。因此,比较rkyvserde的优缺点是有必要的。比如,rkyv的零拷贝特性可以减少反序列化的开销,但可能在跨平台或网络传输时需要注意内存布局的问题。 然后,我需要解释rkyv的核心机制,比如Archive trait、序列化(serialize)反序列化(deserialize)的过程。这里要注意使用正确的术语,并举例说明如何定义可序列化的结构体,以及如何进行操作。需要确保示例代码准确,同时用中文解释清楚每个步骤的作用。 另外,rkyv的安全性也是重点。需要提到其静态验证机制,如何通过类型系统保证反序列化的安全性,避免运行时错误。这可能涉及到验证器(Validator)的作用,以及如何检查数据的有效性。 还有性能方面,rkyv的优势在于不需要在反序列化时复制数据,这对于大型数据结构特别有用。可能需要提到基准测试的结果,但如果没有具体数据,可以强调其设计目标。 用户可能关心的另一个方面是使用场景。比如,rkyv适用于需要高性能低延迟的场景,如游戏、实时系统,而serde更适用于需要灵活性跨平台支持的场景。需要明确这些适用情况,帮助用户决定是否选择rkyv。 需要注意的潜在问题包括内存对齐、字节序问题,以及在不同平台或语言之间传输时的限制。这些应该在介绍中提到,作为使用时的注意事项。 最后,结构要清晰,分点讲解,可能包括概述、核心特性、使用示例、与serde的对比、注意事项等部分。确保每个部分都有足够的细节,但不过于冗长。同时,按照系统级指令,数学公式或代码部分要用正确的格式,比如结构体定义用代码块,但这里用户要求的是中文回答,可能需要将代码示例用中文解释,并正确使用$...$或$$...$$格式,如果有数学相关内容的话。 现在需要检查是否有遗漏的关键点,比如rkyv的依赖管理、与其他库的兼容性、社区支持等,但可能这些信息用户暂时不需要,除非特别提到。保持回答的简洁重点突出是关键。同时,要确保遵循用户的格式要求,不使用markdown,用自然的中文分段,结构清晰。</think>以下是关于Rust中**rkyv序列化反序列化**的详细介绍,分步解析其核心概念、优势与使用场景: --- ### 1. rkyv 概述 **rkyv**(发音为 "archive")是一个高性能的零拷贝(zero-copy)序列化框架,专为Rust设计。其核心目标是通过直接操作内存布局,避免反序列化时的数据复制,从而显著提升性能。主要特点包括: - **零拷贝反序列化**:反序列化时不复制数据,直接通过指针访问内存。 - **高性能**:序列化反序列化速度接近原生内存操作。 - **内存安全**:依赖Rust的所有权系统,避免内存安全问题。 --- ### 2. 核心机制 #### (1) 内存布局直接映射 rkyv将Rust结构体的内存布局直接序列化为字节流,反序列化时只需验证字节流的有效性,即可通过类型转换直接访问数据。例如: ```rust #[derive(Archive, Serialize, Deserialize)] struct Data { id: u32, value: f64, } ``` - **`Archive` trait**:生成一个与原始结构体内存布局兼容的归档版本(如 `ArchivedData`)。 - **序列化**:将 `Data` 转换为字节流。 - **反序列化**:将字节流转换为 `ArchivedData`,无需复制数据。 #### (2) 零拷贝验证 反序列化时,通过 `check_archived_root` 验证字节流的有效性: ```rust let bytes = rkyv::to_bytes::<_, 256>(&data).unwrap(); let archived = rkyv::check_archived_root::<Data>(&bytes).unwrap(); ``` 此步骤仅验证字节对齐类型安全性,不涉及数据拷贝。 --- ### 3. 性能优势 - **反序列化开销趋近于零**:对于大型数据集(如数组、树形结构),性能比传统序列化库(如`serde`+`bincode`)快10-100倍。 - **适用场景**:游戏引擎、实时数据处理等对延迟敏感的应用。 --- ### 4. 与 Serde 的对比 | 特性 | rkyv | Serde(如bincode/json) | |---------------------|-------------------------------|-------------------------------| | **反序列化方式** | 零拷贝,直接访问内存 | 逐字段解析并重建对象 | | **性能** | 极低延迟,适合高频操作 | 适用于通用场景 | | **跨平台/网络传输** | 需处理字节序对齐问题 | 天然支持跨平台 | | **灵活性** | 需预先定义 `Archive` 类型 | 支持动态类型(如JSON) | --- ### 5. 使用示例 #### 基本流程: 1. **定义可序列化结构体**: ```rust use rkyv::{Archive, Serialize, Deserialize}; #[derive(Archive, Serialize, Deserialize, Debug)] struct User { id: u64, name: String, } ``` 2. **序列化**: ```rust let user = User { id: 42, name: "Alice".to_string() }; let bytes = rkyv::to_bytes::<_, 256>(&user).unwrap(); ``` 3. **反序列化(零拷贝)**: ```rust let archived = rkyv::check_archived_root::<User>(&bytes).unwrap(); println!("User ID: {}", archived.id); // 直接访问字段 ``` --- ### 6. 注意事项 - **内存对齐**:归档类型需与原始类型的内存布局完全一致。 - **字节序问题**:跨平台传输时需处理大端/小端字节序。 - **版本兼容性**:结构体字段修改可能导致旧数据无法反序列化--- ### 7. 适用场景 - **高频读操作**:如ECS(Entity-Component-System)架构中的组件存储。 - **内存敏感应用**:嵌入式系统或资源受限环境。 - **实时数据处理**:需要微秒级反序列化的场景。 --- 通过上述设计,rkyv在特定场景下提供了近乎极致的性能,但需权衡其与跨平台灵活性之间的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值