Reputation: 5384
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
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