如何将 JSON 反序列化为具有 Box<[u8]> 值的结构?

问题描述

我有一个需要包含“字节”字段的结构,我正在尝试从 JSON 中反序列化它。

当我使用 &'a [u8] 时,这有效,但随后我需要向该结构以及包含它的结构添加生命周期注释,依此类推。

我以为我可以通过“拥有”字节并使用封闭的 Box解决这个问题,但这不起作用。我正在尝试弄清楚为什么不,或者是否有办法(使用一些 serde 注释,或该字段的自定义帮助程序,或其他方法)使其工作。

更具体地说,这是有效的:

struct Foo<'a> {
  some_field: Option<String>,field_of_interest: &'a [u8],}

这不会:

struct Foo {
  some_field: Option<String>,field_of_interest: Box<[u8]>,}

在这两种情况下,我都将其称为:

let my_foo: Foo = serde_json::from_slice(...);

我在将 Box 替换为 Vec(即 Vec<u8>)时遇到了同样的问题

使用解决方案进行编辑:

正如@lpiepiora 在下面指出的,这需要一个额外的包装器。类似于以下内容,由 serde_bytes crate 提供:

#[cfg(any(feature = "std",feature = "alloc"))]
impl<'de> Deserialize<'de> for Box<[u8]> {
    fn deserialize<D>(deserializer: D) -> Result<Self,D::Error>
    where
        D: Deserializer<'de>,{
        Deserialize::deserialize(deserializer).map(Vec::into_Boxed_slice)
    }
}

解决方法

假设您尝试将 JSON 字符串反序列化为 Vec<u8>,您可以添加一个 crate serde_bytes

例如:

use serde::Deserialize;

#[derive(Deserialize,Debug)]
struct Foo {
      a: Option<String>,#[serde(with = "serde_bytes")]
      b: Vec<u8>
}

fn main() {
    let x = b"{ \"a\": \"a-value\",\"b\": \"aaaaaaaa\" }";
    let my_foo: Foo = serde_json::from_slice(x).unwrap();
    println!("{:?}",my_foo);
}

将打印:Foo { a: Some("a-value"),b: [97,97,97] }

通常Vec<u8> expects an array