【问题标题】:How do I create a Rust HashMap where the value can be one of multiple types?如何创建值可以是多种类型之一的 Rust HashMap?
【发布时间】:2017-01-01 23:06:26
【问题描述】:

我想制作一个包含多种类型的 JSON 对象。这是结构:

{
    "key1": "value",
    "key2": ["val", "val", "val"]
    "key3": { "keyX": 12 }
}

如何创建一个接受所有这些类型的HashMap?

我正在尝试这个:

let item = HashMap::new();
item.insert("key1", someString); //type is &str
item.insert("key2", someVecOfStrings); //type is Vec<String>
item.insert("key3", someOtherHashMap); //Type is HashMap<&str, u32>

let response = json::encode(&item).unwrap();

我知道哈希映射没有足够的类型信息,但我不确定如何使它工作。我尝试在item 上设置一个显式类型,即HashMap&lt;&amp;str, Encodable&gt;,但这只是另一个错误。这样做的正确方法是什么?

【问题讨论】:

    标签: hashmap rust


    【解决方案1】:

    您应该在HashMap 中使用枚举类型作为值。该枚举需要为每种可能的类型(布尔、数字、字符串、列表、映射...)提供一个变体,并为每个变体提供一个适当类型的关联值:

    enum JsonValue<'a> {
        String(&'a str),
        VecOfString(Vec<String>),
        AnotherHashMap(HashMap<&'a str, u32>),
    }
    

    幸运的是,已经有了an implementation of a JSON value type,它是serde_json crate 的一部分,它建立在serde crate 之上。

    如果您使用 serde_json crate,您的代码将如下所示:

    extern crate serde_json;
    
    use serde_json::{Value, Map, Number};
    
    fn main() {
        let mut inner_map = Map::new();
        inner_map.insert("x".to_string(), Value::Number(Number::from(10u64)));
        inner_map.insert("y".to_string(), Value::Number(Number::from(20u64)));
    
        let mut map = Map::new();
        map.insert("key1".to_string(), Value::String("test".to_string()));
        map.insert(
            "key2".to_string(),
            Value::Array(vec![
                Value::String("a".to_string()),
                Value::String("b".to_string()),
            ]),
        );
        map.insert("key3".to_string(), Value::Object(inner_map));
    
        println!("{}", serde_json::to_string(&map).unwrap());
        // => {"key1":"test","key2":["a","b"],"key3":{"x":10,"y":20}}
    }
    

    【讨论】:

    • 您能否提供一个示例如何执行我在问题中发布的示例?除了使用枚举之外没有其他方法吗?与其他语言相比,这似乎有点矫枉过正,但我​​不知道 Rust 是如何做到的,因为我才刚刚开始。
    • This crate 还可以让您轻松编写 JSON。
    • 我添加了一个示例。为什么你认为这是矫枉过正?这是对 rust 枚举(标记的联合)的非常简单的使用。
    【解决方案2】:

    这是另一种可能更适合您的方法。 serde_json crate 提供了一种从 JSON 文字构造 serde_json::Value 对象的方法。您的示例如下所示:

    #[macro_use]
    extern crate serde_json;
    
    fn main() {
        let item = json!({
            "key1": "value",
            "key2": ["val", "val", "val"],
            "key3": { "keyX": 12 }
        });
    
        let response = serde_json::to_string(&item).unwrap();
    }
    

    【讨论】:

      猜你喜欢
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多