如何从“.”生成 serde_json 对象分隔的文本格式?
How do I generate a serde_json object from a "." separated text format?
问题
我正在尝试通过解析如下所示的自定义宏格式来生成 json 对象(使用 serde):
Plot.Polar.max: 20
Plot.Polar.min: 0
Plot.Polar.numberlabel: 0101
Plot.Polar.chartname: small-chart
Plot.Polar.Var.1:
Plot.Polar.Var.2: A label: with T+ES[T] #Data
我卡住的是如何为对象设置键。在我的旧 JavaScript 代码中,我拆分了 \n
、.
和 :
,有几个嵌套循环,最后有一个 reduceRight 来创建这样的对象:
// rowObject equals one row in the old macro format
let rowObject = keys.reduceRight(
(allKeys, item) => ({ [item]: allKeys }),
val,
);
我的目标
我的目标是使用那个 json 对象根据自定义宏中的键和值生成 highcharts 配置 (json)。我也希望能够仅以 json 格式打印宏,因此为什么我想先将宏转换为 json 而不是使用单独的数据结构(尽管这可能是个好主意? ).我想从宏中生成的 json 是这样的:
{
"Plot": {
"Polar": {
"max": 20,
"min": 0
}
}
}
我试过的
Map::insert
虽然我不确定如何构造密钥字符串。在这种情况下如何管理地图对象?
- 我看到的另一种解决方案是从原始字符串创建对象并将每个 rowObject 与主对象合并,尽管这种方法感觉有点老套。
我的当前循环:
// pseudo
// let mut json_macro = new Map();
for row in macro_rows.iter() {
let row_key_value: Vec<&str> = row.split(':').collect();
let keys = row_key_value[0];
let value = row_key_value[1];
let keys_split: Vec<&str> = keys.split('.').collect();
for key in keys_split.iter() {
// TODO: accumulate a objects to row_object
}
// TODO: insert row_object to json_macro
}
问题
是否可以在 JavaScript 中执行类似 reduceRight 的操作或在 rust 中执行类似的操作?
更新
我意识到我必须将所有值都视为字符串,因为不可能知道数字是否是字符串。最终起作用的是@gizmo 提供的解决方案。
要将您的行插入 json_macro
,您可以从左侧折叠 keys_split
并将每个键插入 top-level 对象:
let row_key_value: Vec<&str> = row.split(':').collect();
let keys = row_key_value[0];
let value: Value = serde_json::from_str(row_key_value[1]).unwrap();
let keys_split: Vec<&str> = keys.split('.').collect();
keys_split[..keys_split.len() - 1]
.iter()
.fold(&mut json_macro, |object, &key| {
object
.entry(key)
.or_insert(Map::new().into())
.as_object_mut()
.unwrap()
})
.insert(keys_split.last().unwrap().to_string(), value);
这里有一些关于 unwrap()
s 的注意事项:
from_str(...).unwrap()
:我在这里将val
解析为JSON对象。这可能不是您想要的。也许您想要 str::parse::<i32>
或其他东西。无论如何,此解析可能会失败。
.as_object_mut().unwrap()
:如果输入重新定义键,如 ,这将爆炸
Plot.Polar: 0
Plot.Polar.max: 20
- 反过来,您可能希望处理键已定义为对象的情况。
keys_split.last().unwrap()
不会失败,但您可能想检查它是否为空字符串
问题
我正在尝试通过解析如下所示的自定义宏格式来生成 json 对象(使用 serde):
Plot.Polar.max: 20
Plot.Polar.min: 0
Plot.Polar.numberlabel: 0101
Plot.Polar.chartname: small-chart
Plot.Polar.Var.1:
Plot.Polar.Var.2: A label: with T+ES[T] #Data
我卡住的是如何为对象设置键。在我的旧 JavaScript 代码中,我拆分了 \n
、.
和 :
,有几个嵌套循环,最后有一个 reduceRight 来创建这样的对象:
// rowObject equals one row in the old macro format
let rowObject = keys.reduceRight(
(allKeys, item) => ({ [item]: allKeys }),
val,
);
我的目标
我的目标是使用那个 json 对象根据自定义宏中的键和值生成 highcharts 配置 (json)。我也希望能够仅以 json 格式打印宏,因此为什么我想先将宏转换为 json 而不是使用单独的数据结构(尽管这可能是个好主意? ).我想从宏中生成的 json 是这样的:
{
"Plot": {
"Polar": {
"max": 20,
"min": 0
}
}
}
我试过的
Map::insert
虽然我不确定如何构造密钥字符串。在这种情况下如何管理地图对象?- 我看到的另一种解决方案是从原始字符串创建对象并将每个 rowObject 与主对象合并,尽管这种方法感觉有点老套。
我的当前循环:
// pseudo
// let mut json_macro = new Map();
for row in macro_rows.iter() {
let row_key_value: Vec<&str> = row.split(':').collect();
let keys = row_key_value[0];
let value = row_key_value[1];
let keys_split: Vec<&str> = keys.split('.').collect();
for key in keys_split.iter() {
// TODO: accumulate a objects to row_object
}
// TODO: insert row_object to json_macro
}
问题
是否可以在 JavaScript 中执行类似 reduceRight 的操作或在 rust 中执行类似的操作?
更新
我意识到我必须将所有值都视为字符串,因为不可能知道数字是否是字符串。最终起作用的是@gizmo 提供的解决方案。
要将您的行插入 json_macro
,您可以从左侧折叠 keys_split
并将每个键插入 top-level 对象:
let row_key_value: Vec<&str> = row.split(':').collect();
let keys = row_key_value[0];
let value: Value = serde_json::from_str(row_key_value[1]).unwrap();
let keys_split: Vec<&str> = keys.split('.').collect();
keys_split[..keys_split.len() - 1]
.iter()
.fold(&mut json_macro, |object, &key| {
object
.entry(key)
.or_insert(Map::new().into())
.as_object_mut()
.unwrap()
})
.insert(keys_split.last().unwrap().to_string(), value);
这里有一些关于 unwrap()
s 的注意事项:
from_str(...).unwrap()
:我在这里将val
解析为JSON对象。这可能不是您想要的。也许您想要str::parse::<i32>
或其他东西。无论如何,此解析可能会失败。.as_object_mut().unwrap()
:如果输入重新定义键,如 ,这将爆炸
Plot.Polar: 0
Plot.Polar.max: 20
- 反过来,您可能希望处理键已定义为对象的情况。
keys_split.last().unwrap()
不会失败,但您可能想检查它是否为空字符串