Как десериализовать 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:

#[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)
    }
}

person agam    schedule 30.04.2021    source источник
comment
С какой проблемой вы столкнулись с _1 _ / _ 2_?   -  person John Kugelman    schedule 30.04.2021
comment
@agam Я предполагаю, что вы хотите десериализовать строку JSON в Box<[u8]> (потому что массив десериализуется без проблем). Посмотрите на этот ящик docs.serde.rs/serde_bytes, он должен помочь   -  person lpiepiora    schedule 30.04.2021
comment
Собственная версия фрагмента - Vec. Vec<u8> (без скобок) пробовали? Если не работает, можете ли вы поделиться JSON?   -  person Co_42    schedule 30.04.2021
comment
@ Co_42 да, пробовал Vec<u8>, обновил, чтобы отразить. @lpiepiora спасибо, что сработало !! (теперь я пойду понять почему). Пожалуйста, добавьте однострочный ответ, чтобы я пометил его как правильный :-)   -  person agam    schedule 30.04.2021


Ответы (1)


Предполагая, что вы пытаетесь десериализовать строку JSON в Vec<u8>, вы можете добавить ящик 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, 97, 97, 97, 97, 97] }.

Обычно Vec<u8> ожидает массив .

person lpiepiora    schedule 30.04.2021