rust结构体包含另一个结构体引用时,serde序列化问题

代码如下

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct Person {
    id: String,
    name: String,
}

#[derive(Serialize, Deserialize)]
struct Msg<'a> {
    id: String,
    person: &'a Person,
}

fn main() {
    let person = Person {
        id: "123".to_string(),
        name: "Alice".to_string(),
    };

    let msg = Msg {
        id: "456".to_string(),
        person: &person,
    };

    let msg_str = serde_json::to_string(&msg).unwrap();
    println!("Serialized Msg: {}", msg_str);
}

报错如下

error[E0277]: the trait bound `&'a Person: Deserialize<'_>` is not satisfied
    --> src/main.rs:2463:13
     |
2463 |     person: &'a Person,
     |             ^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `&'a Person`
     |
note: required by a bound in `next_element`
    --> /home/alxps/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.195/src/de/mod.rs:1726:12
     |
1724 |     fn next_element<T>(&mut self) -> Result<Option<T>, Self::Error>
     |        ------------ required by a bound in this associated function
1725 |     where
1726 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `SeqAccess::next_element`
help: consider removing the leading `&`-reference
     |
2463 -     person: &'a Person,
2463 +     person: Person,
     |

我不想让msg有person所有权,也不想clone person,现在要自定义序列化实现trait,person字段类型改成Cow<'a, Person>之类的就好了。代码修改如下

use std::borrow::Cow;
use serde::{Deserialize, Serialize};

#[derive(Clone, Serialize, Deserialize)]
struct Person {
    id: String,
    name: String,
}

#[derive(Serialize, Deserialize)]
struct Msg<'a> {
    id: String,
    person: Cow<'a, Person>,
}

fn main() {
    let person = Person {
        id: "123".to_string(),
        name: "Alice".to_string(),
    };

    let msg = Msg {
        id: "456".to_string(),
        person: Cow::Borrowed(&person),
    };

    let msg_str = serde_json::to_string(&msg).unwrap();
    println!("Serialized Msg: {}", msg_str);
}

参考链接 

1、rust中文社区提问

2、稀土掘金rust Cow博客

 


链接:https://www.zhihu.com/question/405620851/answer/1331050339

Rust 的反序列化效率还取决于如何定义这个 User 结构

之前的回答里使用的是:

#[derive(Deserialize)]
struct User {
    name: String,
    age: i32,
    blog: String,
    addr: String,
}

而如果你不需要把这个 User 结构传到当前作用域外部,可以定义成这样:

#[derive(Deserialize)]
struct User<'a> {
    name: &'a str,
    age: i32,
    blog: &'a str,
    addr: &'a str,
}

或者如果你有可能修改它的话可以定义成这样:

#[derive(Deserialize)]
struct User<'a> {
    #[serde(borrow)]
    name: Cow<'a, str>,
    age: i32,
    #[serde(borrow)]
    blog: Cow<'a, str>,
    #[serde(borrow)]
    addr: Cow<'a, str>,
}

这样可以实现零拷贝反序列化,不会额外进行堆分配和内存拷贝,其中的 name、blog、addr 只是引用源 json 字符串的切片。

性能有多大提升大家自己试试吧。

 

posted @ 2024-02-20 15:48  ALXPS  阅读(102)  评论(0编辑  收藏  举报