JSON 可能是最常用的数据结构。您可以将其用于配置、数据库等。
json 数据结构的最佳实践都是针对每个属性都有静态键的情况,但但有时我们需要处理动态键。
serde_json
在 rust 中,我们使用的是 serde_json 库,它有很好的 api 可以使用。那么我们来看看如何用serde_json解析json。
让我们将 serde 依赖添加到Cargo.toml。我们将使用serde将我们的数据序列化为 struct。
serde = { version = "1.0", features = ["derive"] } |
现在让我们解析一些带有静态键属性的 json:
use serde::{Deserialize, Serialize}; |
使用静态键属性,我们可以轻松地向结构声明键和类型。但是,如果密钥是动态的,我们将无法处理。
动态Json
幸运的是 serde_json 有这个枚举来处理 json 数据结构:
enum Value { |
使用这个枚举,我们可以检查每个键并对其进行一些序列化。现在,假设我们有这个 json:
{ |
看起来很简单吧?我们可以像这样轻松地声明结构。
#[derive(Serialize, Deserialize)] |
但是,如果插件中的键是动态的,例如,如果z_index变成了z-index,而且键的数量超过了例子中的三个,怎么办?
#[derive(Serialize, Deserialize)] |
现在我们可以像这样访问数据:
let data: Data = serde_json::from_str(json)?; |
要把Value变成数组,我们可以这样做:
let z_index_arr: Vec<&Value> = z_index.as_array().unwrap(); |
我们也可以通过将z_index里面的值转化为键值来进行改进,它是一个数组。正如你所看到的,z_index的值是数组中的数组。
[ |
让我们把这个值变成:
{ |
为了做到这一点,我们将直接使用Maplet z_index: Vec<&Value> = data.get("z-index").unwrap().as_array().unwrap();
let mut data = Map::new();
for item in z_index {
if item.get(0)?.is_string() {
let key = item.get(0)?.as_str()?.to_string();
let variants = item.get(1)?.clone();
}
}
小提示! 如果你不想每次转换枚举值时都使用unwrap(),只需使用? 并用Option<()>来包装你的函数
现在我们可以这样访问z-index的值:let arr: Vec<&Value> = data.get("z")?;
serde 的更多文档。