如何在Rust中过滤多维数组?基于Serde的JSON数据筛选问题
问题
我有如下JSON数据,需要用Rust结合Serde库解析。目前能通过以下代码访问部分内容:
let v: serde_json::Value = serde_json::from_str(&data).expect("Unable to parse"); let sessions = v["data"]["sessions"].as_array().unwrap(); let programs = v["data"]["programs"].as_array().unwrap();
但我想通过programs.id的值筛选出对应的programData数组项,尝试了下面的代码却编译报错,提示‘no implementation’:
for x in programs { let programId = &x["id"]; // 无法运行——编译时出现‘no implementation’错误 let programSessions = sessions.iter().filter(|&f| f["programData"].as_array().unwrap()["programRefId"] == programId).collect(); }
对应的JSON数据:
{ "data": { "name": "my name", "sessions": [ { "id": 1, "programData": [ { "dataPhase": 1, "programRefId": 2, "programSpecificData": { "completed": false } }, { "dataPhase": 2, "programRefId": 3, "programSpecificData": { "completed": true } } ] } ], "programs": [ { "id": 3 } ] } }
解决方案
你的代码存在两个核心问题:
- 数组访问逻辑错误:
f["programData"].as_array().unwrap()得到的是数组类型,直接用["programRefId"]索引数组是无效操作——数组需要遍历内部元素才能获取每个元素的programRefId。 - 类型推断与比较问题:
serde_json::Value的比较需要保证类型完全一致,且collect()未指定目标类型,Rust无法自动推断。
修复后的完整代码如下:
use serde_json::Value; fn main() { let data = r#"{ "data": { "name": "my name", "sessions": [ { "id": 1, "programData": [ { "dataPhase": 1, "programRefId": 2, "programSpecificData": { "completed": false } }, { "dataPhase": 2, "programRefId": 3, "programSpecificData": { "completed": true } } ] } ], "programs": [ { "id": 3 } ] } }"#; let v: Value = serde_json::from_str(data).expect("Unable to parse"); let sessions = v["data"]["sessions"].as_array().unwrap(); let programs = v["data"]["programs"].as_array().unwrap(); for program in programs { // 将program.id转为具体数值类型,避免Value比较的潜在类型不匹配问题 let program_id = program["id"].as_i64().unwrap(); // 遍历所有session,筛选出匹配的programData项 let matched_program_data: Vec<&Value> = sessions .iter() // 展开每个session的programData数组,将嵌套数组转为平铺的元素流 .flat_map(|session| session["programData"].as_array().unwrap()) // 筛选programRefId与当前program.id匹配的项 .filter(|data_item| data_item["programRefId"].as_i64().unwrap() == program_id) .collect(); println!("匹配到的programData项: {:?}", matched_program_data); } }
关键修正点说明
- 用
flat_map处理嵌套数组:把每个session内部的programData数组展开,让后续的筛选逻辑能直接遍历到单个programData元素。 - 统一数值类型:将
program.id和programRefId都转为i64类型,确保比较操作的类型一致性,避免serde_json::Value不同子类型无法比较的报错。 - 明确集合类型:给
collect()指定Vec<&Value>类型,让Rust能正确推断最终生成的集合类型。
内容的提问来源于stack exchange,提问作者HBCondo
相关产品推荐
相关产品推荐

