Rust遍历JSON键值对填充HashMap时遇序列化错误
Rust处理JSON时serde_json与ajson跨库类型兼容问题解决
问题场景
从PHP转Rust,通过实战项目学习,需要处理运行时JSON文件,提取indinces部分数据并重构格式。当前代码混用ajson和serde_json库,出现编译错误。
当前代码
use { std::{ fs::*, path::Path, collections::{HashMap}, }, ajson::*, serde_json::*, } pub async fn process() -> HashMap<String, Object> { let mut return_hash: HashMap<String, Object> = HashMap::new(); let path = "./downloadFolder/APIReturn/a33562.json"; let json = &std::fs::read_to_string(path).expect("Unable to read file"); let default_map = ajson::get(json, "Defaults.Settings").expect("JSON was not well-formatted"); let indince_map = ajson::get(json, "indinces").expect("JSON was not well-formatted"); let mut loop_count = 0; for (key, value) in serde_json::json!(indince_map){ return_hash.insert(key.to_string(), indince::new(key, value)); } // 原代码缺少return语句,此处补充完整 return_hash }
目标JSON结构
{ "Defaults":{ "settings": { "Angle": 90, "Region": "27B", "Area": 187 } }, "indinces": { "Springfield": { "Angle": 45, "Area": 285 }, "Lawrence": { "Region": "38A" } } }
报错信息
for (key, value) in serde_json::json!(indince_map){ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | the trait `Serialize` is not implemented for `ajson::Value<'_>` | required by a bound introduced by this call
问题原因
serde_json::json!宏要求传入参数实现Serialize trait,但ajson::Value类型并未实现该trait,跨库类型不兼容导致无法直接转换。
解决方案
方案一:统一使用serde_json处理(推荐)
放弃混用ajson,全程用serde_json解析和操作JSON,避免跨库类型冲突:
use std::{ fs::read_to_string, collections::HashMap, }; use serde_json::{Value, Map}; pub async fn process() -> HashMap<String, Map<String, Value>> { let mut return_hash = HashMap::new(); let path = "./downloadFolder/APIReturn/a33562.json"; let json_str = read_to_string(path).expect("Unable to read file"); let json: Value = serde_json::from_str(&json_str).expect("JSON was not well-formatted"); // 提取默认设置(按需保留) let default_map = json["Defaults"]["settings"].clone(); // 提取indinces并遍历 if let Value::Object(indinces) = &json["indinces"] { for (key, value) in indices { let obj = indince::new(key.as_str(), value); return_hash.insert(key.clone(), obj); } } return_hash }
方案二:使用ajson自身的遍历方法
若坚持使用ajson,可将indince_map转换为ajson::Object后直接遍历:
use { std::{ fs::read_to_string, collections::HashMap, }, ajson::{self, Object, Value}, }; pub async fn process() -> HashMap<String, Object> { let mut return_hash = HashMap::new(); let path = "./downloadFolder/APIReturn/a33562.json"; let json_str = read_to_string(path).expect("Unable to read file"); let default_map = ajson::get(&json_str, "Defaults.settings").expect("JSON was not well-formatted"); let indince_map = ajson::get(&json_str, "indinces").expect("JSON was not well-formatted"); // 将ajson::Value转换为Object并遍历 if let Value::Object(indinces) = indince_map { for (key, value) in indices { if let Value::Object(obj) = value { return_hash.insert(key, obj); } } } return_hash }
补充说明
- Rust类型系统严格,跨库类型无法隐式转换,处理JSON时建议统一使用一个库(serde_json是Rust生态最常用的JSON处理库,优先推荐)
- 原代码存在拼写错误:
indince应为indices(复数形式),建议修正避免后续混淆
内容的提问来源于stack exchange,提问作者lilHar
相关产品推荐
相关产品推荐

