【问题标题】:How do I use `serde_json_core` to deserialise an array without allocations?如何使用 `serde_json core` 反序列化没有分配的数组?
【发布时间】:2021-11-15 14:41:13
【问题描述】:

如何在不使用 serde_json_core 或类似方法执行堆分配的情况下反序列化 JSON {"arr":[1,2,3,4]}?它当前执行一个分配。我看到 serde_json_core 使用 heapless 板条箱,但我不确定如何让它们一起工作。

#[derive(Deserialize)]
struct MyStruct {
    arr: Vec<u64>,
}

fn main() {
    let j = r#"{"arr":[1,2,3,4]}"#;

    let r: serde_json_core::de::Result<(MyStruct, usize)> = serde_json_core::from_str(j);
    let (out, _) = r.unwrap();

    println!("First value: {}.",  out.arr[0]);
}

我正在使用serde_json_core = 0.4.0

【问题讨论】:

  • 你事先知道数组的确切大小吗?如果是这样,您可以简单地反序列化为固定大小的数组[u64; N]。如果没有,您需要确定您希望能够反序列化的最大可能数组大小。您需要预先分配堆栈上的所有内容,因此您不能支持任意大小。使用Vec 不是一个选项,因为如果它包含任何元素,它将分配。
  • 谢谢,我知道数组的长度必须小于或等于 10 个元素。不幸的是,如果我这样做[u64; 10],我会得到'called 'Result::unwrap()' on an 'Err' value: CustomError'。我需要数组大小正好为 4 ([u64; 4]) 才能工作。
  • 对于可变大小,不能使用固定大小的数组。您需要使用一些堆栈分配的类似矢量的数据结构,例如heapless::Vec。您应该能够将use serde_json_core::heapless::Vec; 添加到您的代码中,然后将10 作为第二个模板参数添加到MyStruct 内的Vec
  • 这是我在使用serde_json_core 时最初的希望,但是Deserialize 特性并未针对heapless::Vec 的所有变体实现:the trait 'Deserialize&lt;'_&gt;' is not implemented for 'serde_json_core::heapless ::Vec&lt;u64, 4_usize&gt;。我可以自己实现Deserialize 以获得我想要的Vec 容量,但希望我不必这样做。
  • 您需要为heapless 启用serde 功能才能获得实现。

标签: rust serde


【解决方案1】:

serde-json-core crate 可以将 JSON 数组反序列化为任何实现 Deserialize 特征的类型。如果你想避免内存分配,你需要选择一个不分配的容器。

如果事先知道数组的大小,则可以简单地使用固定大小的数组,即[T; N]。如果 JSON 数组的大小不完全是 N,这将返回反序列化错误。

如果 JSON 数组的大小可变且具有已知上限,则可以使用各种类似向量的堆栈分配数据结构之一。一个这样的选项是heapless::Vec,如果您为heapless 启用serde 功能,它将实现Deserialize。在您的 Cargo.yaml 文件中,您可以这样做:

heapless = { version = "0.7", features = ["serde"] }

如果您使用与您的 serde-json-core 版本所依赖的相同版本的 heapless,则它只会包含在您的构建中一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    相关资源
    最近更新 更多