agam
agam

Reputation: 5384

How to deserialize JSON into a structure with a Box<[u8]> value?

I have a struct that needs to include a "bytes" field, and I'm trying to deserialize it from JSON.

When I use &'a [u8], this works, but then I need to add a lifetime annotation to this struct, and the struct that encloses it, and so on.

I thought I'd get around it by having the bytes "owned" and use an enclosing Box, but that didn't work. I'm trying to figure out why not, or whether there's a way (either with some serde annotations, or a custom helper for this field, or something else) to get this to work.

More concretely, this works:

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

And this does not:

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

In both cases, I'm calling it as:

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

I encountered the same issue when replacing Box with Vec (i.e. as Vec<u8>)

Edit with solution:

As @lpiepiora pointed out below, this needs an additional wrapper. Something like the following, which is provided by the 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)
    }
}

Upvotes: 1

Views: 4204

Answers (1)

lpiepiora
lpiepiora

Reputation: 13749

Assuming, that you're trying to deserialize JSON string to Vec<u8>, you can add a crate serde_bytes.

For example:

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);
}

Would print: Foo { a: Some("a-value"), b: [97, 97, 97, 97, 97, 97, 97, 97] }.

Normally Vec<u8> expects an array.

Upvotes: 2

Related Questions