将json转换为TreeMap <string,string =“”> </string,>

时间:2014-12-03 06:09:57

标签: json rust

我想以简单的方式将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")
}

2 个答案:

答案 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!()
};