我想以简单的方式将json转换为TreeMap
,这是我的尝试:
extern crate serialize;
use serialize::json;
use serialize::json::ToJson;
use serialize::json::Json;
use std::collections::TreeMap;
fn main() {
let mut tree_map1 = TreeMap::new();
tree_map1.insert("key1".to_string(), "val1".to_json());
tree_map1.insert("key2".to_string(), "val2".to_json());
//... and so on, the number of keys aren't known
let json1 = json::Object(tree_map1);
let mut tree_map2 = TreeMap::new();
for (k, v) in json1.iter() { //impossible to iterate
tree_map2.insert(k.to_string(), v.to_string());
}
}
更新:
如何将TreeMap<String, json::Json>
转换为TreeMap<String, String>
?
let json1 = get_json1(); // json made of TreeMap<String, json::Json>
let res = match json1 {
json::Object(json2) => json2.map(|k, v| ??? ),
_ => panic!("Error")
}
答案 0 :(得分:3)
以下是将Json
安全地转换为TreeMap<String, String>
的演示文稿:
use serialize::json::Json;
use std::collections::TreeMap;
fn extract_string_map(json: Json) -> Result<TreeMap<String, String>, Json> {
let json = match json {
Json::Object(json) => json,
_ => return Err(json),
};
if !json.iter().all(|(_k, v)| v.is_string()) {
return Err(Json::Object(json));
}
Ok(json.into_iter().map(|(k, v)| (k, match v {
Json::String(s) => s,
_ => unreachable!(),
}))
.collect())
}
这证明了避免恐慌行为的原则,因为不能失败。此外,它不会丢失任何数据 - 如果数据不符合格式,原始数据将完整返回,以便调用者决定如何处理它,而无需在任何时候克隆数据。
(作为一个好奇心,我认为TreeMap的这种重组效率会相当低,需要对树进行更多的重新平衡,因为按键是按顺序给出的。对于性能而言,它是很高兴有一个TreeMap的值更改方法,消耗self并更有效地生成新类型。)
答案 1 :(得分:2)
json::Object
是一个枚举变体,其中包含TreeMap
。因此,为了从中获取TreeMap
,您只需要打开它:
let json1 = json::Object(tree_map1);
let tree_map2 = match json1 {
json::Object(tm) => tm,
_ => unreachable!()
};
这会消耗json1
。如果您不想要它,则需要克隆地图:
let tree_map2 = match json1 {
json::Object(ref tm) => tm.clone(),
_ => unreachable!()
};
使用as_object()
方法可以减少后者的重写:
let tree_map2 = json1.as_object().unwrap().clone();
如果您需要从TreeMap<String, String>
变体中包含的TreeMap<String, Json>
获取Object
,则需要以某种方式将Json
转换为String
。如果您事先知道所有值都是JSON字符串,则可以再次使用模式匹配:
let tree_map2 = match json1 {
json::Object(tm) => tm.into_iter().map(|(k, v)| (k, match v {
json::String(s) => s,
_ => unreachable!()
})).collect(),
_ => unreachable!()
};