在编译时使用serde_json反序列化文件

问题描述 投票:0回答:1

程序开始时,我从文件中读取数据:

let file = std::fs::File::open("data/games.json").unwrap();
let data: Games = serde_json::from_reader(file).unwrap();

由于以下原因,我想知道如何在编译时执行此操作:

  1. 性能:无需在运行时反序列化
  2. 可移植性:该程序可以在任何计算机上运行,​​而无需包含包含数据的json文件。

我可能还会提到,数据只能读取,这意味着解决方案可以将其存储为静态。

rust deserialization json-deserialization serde
1个回答
0
投票

这实际上非常简单,但是会导致一些潜在的问题。首先,我们需要处理一些事情。我们要从文件加载对象树还是在运行时解析它?

99%的时间,在启动时解析为static ref对人们来说足够了,因此,我将为您提供该解决方案;我将在最后指向您指向“其他”版本,但这需要更多的[[lot工作,并且是特定于域的。

您要能够在编译时包含文件的宏(因为它必须是一个宏)在标准库中:std::include_str!。顾名思义,它在编译时获取文件,并从中生成一个std::include_str!供您使用。然后,您可以随意使用它进行任何操作(例如解析)。

[从那里开始,然后使用&'static str为我们的JSON lazy_static!生成一个lazy_static!(或您决定要使用的任何对象)对于程序的每个部分都很简单。例如,在您的情况下,它可能看起来像这样:

static ref

执行此操作时,您需要注意两件事:

    这将
  1. 大量
膨胀文件大小,因为Value不会以任何方式压缩。考虑gzip您需要担心对同一const GAME_JSON:&str = include_str!("my/file.json"); #[derive(Serialize, Deserialize, Debug)] struct Game { name: String } lazy_static! { static ref GAMES:Vec<Game> = serde_json::from_str(&GAME_JSON).unwrap(); } 的多个线程访问的常见问题,但是由于它是不可变的,因此您只需要担心其中的一部分

  • 另一种方法要求在编译时使用&str动态生成对象。如前所述,除非您在解析该JSON时具有很高的启动成本,否则我不建议您这样做。大多数人不会,而我上一次遇到这个是在处理深度嵌套的多GB JSON文件时。
  • 您要查找的板条箱是static refproc-macro,用于代码生成;其余部分与编写普通方法的方式非常相似。

    © www.soinside.com 2019 - 2024. All rights reserved.