在rust开发过程中,我们总是会用到序列化,反序列化,之前我们就介绍了serde这个优秀的序列化框架,不知道的同学可以看我往期的文章,那么具体是怎么实现序列化和反序列化的我们还不是很清楚,具体怎么工作的也不清楚,我们今天就来解决这个问题
定义序列化trait
序列化最核心的接口就是Serialize和Deserialize两个,其中Deserialize是反序列化trait,具体的trait定义如下:
pub trait Serialize {
fn serialize(&self) -> String;
}
pub trait Deserialize: Sized {
fn deserialize(s: &str) -> Result<Self, String>;
}
给不同类型实现序列化trait
我们可以为不同的数据类型实现对应的trait实现序列化和反序列化,比如说基本类型以及复合类型,比如说我们Vector中存放一个结构体和枚举
use crate::serialization::{Deserialize, Serialize};
use chrono::NaiveDateTime;
use std::collections::HashSet;
use std::fmt::Debug;
// Example implementation for basic types
impl Serialize for i32 {
fn serialize(&self) -> String {
self.to_string()
}
}
impl Deserialize for i32 {
fn deserialize(s: &str) -> Result<Self, String> {
s.parse().map_err(|e| format!("Failed to parse i32: {}", e))
}
}
impl Serialize for String {
fn serialize(&self) -> String {
format!(""{}"", self.replace(""", "\""))
}
}
impl Deserialize for String {
fn deserialize(s: &str) -> Result<Self, String> {
if s.len() >= 2 && s.starts_with('"') && s.ends_with('"') {
Ok(s[1..s.len() - 1].replace("\"", """))
} else {
Err("Invalid string format".to_string())
}
}
}
// Example implementation for additional types
impl Serialize for bool {
fn serialize(&self) -> String {
self.to_string()
}
}
impl Deserialize for bool {
fn deserialize(s: &str) -> Result<Self, String> {
match s {
"true" => Ok(true),
"false" => Ok(false),
_ => Err("Failed to parse bool".to_string()),
}
}
}
impl Serialize for f64 {
fn serialize(&self) -> String {
self.to_string()
}
}
impl Deserialize for f64 {
fn deserialize(s: &str) -> Result<Self, String> {
s.parse().map_err(|e| format!("Failed to parse f64: {}", e))
}
}
impl Serialize for NaiveDateTime {
fn serialize(&self) -> String {
self.format("%Y-%m-%d %H:%M:%S").to_string()
}
}
impl Deserialize for NaiveDateTime {
fn deserialize(s: &str) -> Result<Self, String> {
NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S")
.map_err(|e| format!("Failed to parse NaiveDateTime: {}", e))
}
}
impl<T> Serialize for Vec<T>
where
T: Serialize,
{
fn serialize(&self) -> String {
let serialized_elements: Vec<String> = self.iter().map(|item| item.serialize()).collect();
format!("[{}]", serialized_elements.join(","))
}
}
impl<T> Deserialize for Vec<T>
where
T: Deserialize,
{
fn deserialize(s: &str) -> Result<Self, String> {
let s = s.trim();
if !s.starts_with('[') || !s.ends_with(']') {
return Err("Invalid array format".to_string());
}
let content = &s[1..s.len() - 1];
if content.is_empty() {
return Ok(Vec::new());
}
content
.split(',')
.map(|item| T::deserialize(item.trim()))
.collect()
}
}
impl<T> Serialize for HashSet<T>
where
T: Serialize + Eq + std::hash::Hash,
{
fn serialize(&self) -> String {
let serialized_elements: Vec<String> = self.iter().map(|item| item.serialize()).collect();
format!("{{{}}}", serialized_elements.join(","))
}
}
impl<T> Deserialize for HashSet<T>
where
T: Deserialize + Eq + std::hash::Hash,
{
fn deserialize(s: &str) -> Result<Self, String> {
let s = s.trim();
if !s.starts_with('{') || !s.ends_with('}') {
return Err("Invalid set format".to_string());
}
let content = &s[1..s.len() - 1];
if content.is_empty() {
return Ok(HashSet::new());
}
content
.split(',')
.map(|item| T::deserialize(item.trim()))
.collect::<Result<HashSet<_>, _>>()
}
}
例子
mod serialization;
mod serialization_impl;
use chrono::NaiveDateTime;
use serde_json::json;
use serialization::{Deserialize, Serialize};
// Derive macro simulation using a struct
#[derive(Debug)]
struct Person {
name: String,
age: i32,
}
impl Serialize for Person {
fn serialize(&self) -> String {
format!(
"{{"name":{},"age":{}}}",
self.name.serialize(),
self.age.serialize()
)
}
}
impl Deserialize for Person {
fn deserialize(s: &str) -> Result<Self, String> {
// Basic parser for demonstration
// In a real implementation, you'd want a proper parser
let s = s.trim();
if !s.starts_with('{') || !s.ends_with('}') {
return Err("Invalid object format".to_string());
}
let content = &s[1..s.len() - 1];
let mut name = None;
let mut age = None;
for pair in content.split(',') {
let mut parts = pair.split(':');
let key = parts.next().ok_or("Missing key")?.trim().trim_matches('"');
let value = parts.next().ok_or("Missing value")?.trim();
match key {
"name" => name = Some(String::deserialize(value)?),
"age" => age = Some(i32::deserialize(value)?),
_ => return Err(format!("Unknown field: {}", key)),
}
}
Ok(Person {
name: name.ok_or("Missing name field")?,
age: age.ok_or("Missing age field")?,
})
}
}
// Example usage in main
fn main() {
let person = Person {
name: "John Doe".to_string(),
age: 30,
};
// Serialize
let serialized = person.serialize();
println!("Serialized: {}", serialized);
// Deserialize
match Person::deserialize(&serialized) {
Ok(deserialized) => {
// Format the output as JSON
let formatted = json!({
"name": deserialized.name,
"age": deserialized.age
});
println!("Deserialized (formatted): {}", formatted);
}
Err(e) => println!("Error: {}", e),
}
// Example with NaiveDateTime
let datetime =
NaiveDateTime::parse_from_str("2023-01-01 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
let serialized_datetime = datetime.serialize();
println!("Serialized DateTime: {}", serialized_datetime);
match NaiveDateTime::deserialize(&serialized_datetime) {
Ok(deserialized_datetime) => println!("Deserialized DateTime: {}", deserialized_datetime),
Err(e) => println!("Error: {}", e),
}
// Example with Vec
let numbers = vec![1, 2, 3, 4, 5];
let serialized_numbers = numbers.serialize();
println!("Serialized Vec: {}", serialized_numbers);
match Vec::<i32>::deserialize(&serialized_numbers) {
Ok(deserialized_numbers) => println!("Deserialized Vec: {:?}", deserialized_numbers),
Err(e) => println!("Error: {}", e),
}
// Example with Vec of Status
let statuses = vec![Status::Active, Status::Inactive, Status::Pending];
let serialized_statuses = statuses.serialize();
println!("Serialized Vec<Status>: {}", serialized_statuses);
match Vec::<Status>::deserialize(&serialized_statuses) {
Ok(deserialized_statuses) => {
println!("Deserialized Vec<Status>: {:?}", deserialized_statuses)
}
Err(e) => println!("Error: {}", e),
}
// Example with HashSet of Status
}
#[derive(Debug)]
enum Status {
Active,
Inactive,
Pending,
}
impl Serialize for Status {
fn serialize(&self) -> String {
match self {
Status::Active => ""Active"".to_string(),
Status::Inactive => ""Inactive"".to_string(),
Status::Pending => ""Pending"".to_string(),
}
}
}
impl Deserialize for Status {
fn deserialize(s: &str) -> Result<Self, String> {
match s.trim_matches('"') {
"Active" => Ok(Status::Active),
"Inactive" => Ok(Status::Inactive),
"Pending" => Ok(Status::Pending),
_ => Err("Unknown status".to_string()),
}
}
}
希望大家多多关注我的公众号:花说编程,给你带来rust知识的分享