如何在包含 &'static str 的结构上实现 serde::Deserialize?

loo*_*ops 3 string rust deserialization borrow-checker serde

serde::Deserialize我正在尝试在一个结构体上实现SourceConfig,该结构体包装了一个包含 的结构体&'static str以及它自己的一些数据(游乐场)

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct Config {
    pub name: &'static str,
}

#[derive(Serialize, Deserialize)]
struct SourceConfig {
    config: Config,
    id: u32,
}
Run Code Online (Sandbox Code Playgroud)

但这给了我一个终生错误:

   Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'de` as defined on the impl at 8:21...
  --> src/lib.rs:8:21
   |
8  | #[derive(Serialize, Deserialize)]
   |                     ^^^^^^^^^^^
note: ...so that the types are compatible
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   = note: expected `SeqAccess<'_>`
              found `SeqAccess<'de>`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   = note: expected `Deserialize<'_>`
              found `Deserialize<'static>`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'de` as defined on the impl at 8:21...
  --> src/lib.rs:8:21
   |
8  | #[derive(Serialize, Deserialize)]
   |                     ^^^^^^^^^^^
note: ...so that the types are compatible
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   = note: expected `MapAccess<'_>`
              found `MapAccess<'de>`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   = note: expected `Deserialize<'_>`
              found `Deserialize<'static>`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors
Run Code Online (Sandbox Code Playgroud)

我尝试添加#[serde(borrow)]configin SourceConfig,但这不起作用,因为Config不是借用的。将其添加到namein中Config也不起作用。我怎样才能正确Deserialize实施SourceConfig

jon*_*sbb 8

您可以在结构上添加一个界限SourceConfig,使'de生命周期等于'static生命周期。

#[derive(Debug, serde::Deserialize)]
pub struct Config {
    pub name: &'static str,
}

#[derive(Debug, serde::Deserialize)]
#[serde(bound(deserialize = "'de: 'static"))]
struct SourceConfig {
    config: Config,
    id: u32,
}

fn main() {
    let j = r#"
{
    "id": 123,
    "config": {
        "name": "John Smith"
    }
}
    "#;
    
    let sc: SourceConfig = serde_json::from_str(&j).unwrap();
    dbg!(sc);
}
Run Code Online (Sandbox Code Playgroud)

但是,您可能不想反序列化 a,&'static str因为这需要您&'static str借用 a。这限制了您只能使用字符串文字,或者您需要泄漏内存才能获取&'static str. String如果您想支持字符串文字,您可能需要一个或一个Cow<'a, str>

另一个问题&'a str是,如果字符串使用转义序列进行序列化,它将无法工作。例如,包含换行符的 JSON 字符串需要\n在反序列化期间进行替换,因此如果您使用&'a str.