您的位置:首页 > 文旅 > 美景 > html网页设计模板下载_产品品牌策划方案_美国今天刚刚发生的新闻_买链接官网

html网页设计模板下载_产品品牌策划方案_美国今天刚刚发生的新闻_买链接官网

2024/12/23 13:59:18 来源:https://blog.csdn.net/neweastsun/article/details/143701880  浏览:    关键词:html网页设计模板下载_产品品牌策划方案_美国今天刚刚发生的新闻_买链接官网
html网页设计模板下载_产品品牌策划方案_美国今天刚刚发生的新闻_买链接官网

在处理HTTP请求时,我们总是需要在数据结构对象(可以是enum、struct等)和序列化数据格式(例如JSON,用与存储或传输,并可以反序列化的格式)之间来回转换。

Serde是一个库(crate),用于高效、通用地序列化和反序列化Rust数据结构。在本文中,我将向您展示如何使用Attributes自定义Serde派生生成的序列化和反序列化实现。

在这里插入图片描述

入门示例

  • 增加依赖

    在项目目录中执行命令:

    cargo add serde --features derive
    cargo add serde_json
    

cargo add 命令自动增加指定包至Cargo.toml文件。serde包使用--features derive 标识,启用强大的派生特性;serde_json包处理Json序列化和反序列化。执行命令之后,Cargo.toml文件被更新:

[dependencies]
serde = { version = "1.0.nnn", features = ["derive"] }
serde_json = "1.0.nnn"

让我们从一个简单的结构体Student开始,它的定义如下所示,并初始化我们的第一个学生tom。

use serde::{Serialize, Deserialize};#[derive(Serialize, Deserialize)]
struct Person {name: String,age: u32,email: String,
}fn main() {let person = Person {name: "John Doe".to_string(),age: 30,email: "john@example.com".to_string(),};let json = serde_json::to_string(&person).unwrap();println!("{}", json);
}

输出将如下所示:

{"name":"John Doe","age":30,"email":"john@example.com"
}

看起来太棒了!但是,实际应用中,生成json需要适用不同场景,如重新命名字段、忽略部分字段、拉平嵌套对象等。下面分别进行举例说明。

命名规范

例如,我们实际上希望使用studentId而不是student_id作为字段名。

  • 字段重命名

使用rename对单个字段进行重命名:

struct Student {pub name: String, #[serde(rename="studentId")pub student_id: String,
}
  • 命名规范

使用rename_all 实现整个struct遵循骆驼命名规则:

#[serde(rename_all = "camelCase")]
struct Student {pub name: String, pub student_id: String,
}

除了camelCase之外,您还可以应用其他的case惯例。取值为小写、大写、PascalCase、camelCase、snake_case、SCREAMING_SNAKE_CASE、kebab-case、scream - kebab-case。

您可能想知道的另一件事是,为什么要重命名字段呢?如果所需的字段名是一个保留的Rust关键字类型,那么它是非常有用的。另一个有用的地方是当您使用enum并且希望使用特定名称在外部标记它时。我们很快就会讲到这个。

忽略字段

Skip可用于不希望序列化或反序列化的字段。下面是一个简单的例子。让我们给Student添加birth_year和age。

struct Student {pub name: String, pub student_id: String,pub birth_year: u32,pub age: u32,
}

我们可能希望动态更新年龄,因此需要对学生的birth_year的引用。但是,当我们发送请求时,应该只显示age字段。这可以使用#[serde(skip)]来解决。

struct Student {pub name: String, pub student_id: String,#[serde(skip)]pub birth_year: u32,pub age: u32,
}

配置后,输出的json对象为:

{"name": "tom","studentId": "J19990","age": 123
}

其中birth_year字段被跳过。最常见的两种使用场景是那些Option字段和空vector。

  • Option

假设员工结构有化名alias_name: Option字段。如果我们想在员工没有这个字段的情况下跳过这个字段,我们可以这样做。

#[serde(skip_serializing_if="Option::is_none")]
pub alias_name: Option<String>

输出json,分为两种情形:

// without alias name
{"name": "tom","studentId": "J19990",
}// with alias name
{"name": "tom","studentId": "J19990","aliasName": "middle"
}
  • vector字段

例如,我们为employee结构体提供了projects: Vec字段。由于员工不是必须负责项目,它可以是一个空向量。

要跳过对空向量的序列化,可以向字段添加以下属性。

#[serde(skip_serializing_if="Vec::is_empty")]
pub projects: Vec<String>,

是否配置忽略字段属性的输出差异,根据请求主体的需求,我们可以在两者之间进行选择。

// 未配置属性skip_serializing_if
{"name": "tom","empId": "J19990","projects": []
}// 增加skip_serializing_if属性配置
{"name": "tom","empId": "J19990"
}

扁平化

当你想结构体的一些字段公开和/或给它们默认值,..Default::default()方式特别有用的。下面示例创建名为SideInfo的新结构体,并将Student结构体更改为以下内容。

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Student {pub name: String, pub student_id: String,#[serde(skip_serializing_if="Option::is_none")]pub side_info: Option<SideInfo>
}#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
struct SideInfo {#[serde(skip_serializing_if="Option::is_none")]pub pets: Option<Vec<String>>,#[serde(skip_serializing_if="Option::is_none")]pub address: Option<String>,
}

为了让SideInfo中address字段有值,其他字段未默认值。可以采用..Default::default()方式创建对象:

let student = Student{name:"dan".to_owned(), student_id: "1".to_owned(), side_info:Some(SideInfo{address:Some("47 street".to_owned()), ..Default::default()})
};

输出json如下:

{"name": "dan","studentId": "1","sideInfo": {"address": "47 street"}
}

从输出看到,地址字段嵌套在sideInfo中。但是,通过将属性flatten添加到Student结构中的sideInfo字段:

  #[serde(skip_serializing_if="Option::is_none", flatten)]pub side_info: Option<SideInfo>

输出json:

{"name": "dan","studentId": "1","address": "47 street"
}

反序列化

除了序列化之外,Serde还简化了将JSON字符串反序列化回Rust结构的过程。反序列化允许我们解析JSON数据并将其转换为有意义的Rust对象。

使用我们的Person结构的例子,我们可以有这样的JSON表示,并通过serde_json::from_str方法进行反序列化:

let json_person = r#"
{"name": "Jane Smith","age": 28,"email": "jane@example.com"
}
"#;let person: Person = serde_json::from_str(json_person).unwrap();
println!("Name: {}", person.name);
println!("Age: {}", person.age);
println!("Email: {}", person.email);

输出结果:

Name: Jane Smith
Age: 28
Email: jane@example.com

错误处理

在大多数现实场景中,您将处理通常不可预测或不正确的数据。Serde允许在反序列化过程中进行错误处理:

#[derive(Serialize, Deserialize, Debug)]
struct User {name: String,age: u8,email: String,
}fn main() {let data = r#"{"name": "John Doe","age": "twenty","email": "john@example.com"}"#;let result: Result<User, _> = serde_json::from_str(data);match result {Ok(_) => println!("Successfully deserialized data"),Err(err) => {println!("We ran into an error: {}", err);match err.classify() {serde_json::error::Category::Io => println!("Problem reading file"),serde_json::error::Category::Syntax => println!("Problem with JSON syntax"),serde_json::error::Category::Data => println!("Problem with data"),serde_json::error::Category::Eof => println!("Unexpected end of file"),}}}
}

在上面的示例中,age字段不正确(它需要数字,但我们输入了字符串)。在Error:: classifier函数的帮助下,可以对错误进行分类并决定如何处理它。

常见问题

  1. serde支持自定义序列化?

    回答:支持,serde提供自定义序列化和反序列方式

  2. serde支持那些数据格式?

    回答:serde支持很多数据格式,包括:JSON, YAML, MessagePack, 和BSON等。

  3. serde中**serde_derive**的作用?

​ 回答:**serde_derive**是过程宏,使用它可以自动给结构体派生SerializeDeserialize 实现。

  1. 对于大数据结构serde性能如何?

    回答:它使用Rust的类型系统来减少需要运行时工作量,因此性能和效率非常高。

最后总结

本文介绍了Rust中serde包较为全面的使用指南,可以帮助你更好理解如何使用Serde实现序列化。它是一个高度通用和强大的库,是Rust程序开发中必不可少的工具包。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com