简体   繁体   English

如何创建 Rust HashMap,其中值可以是多种类型之一?

[英]How do I create a Rust HashMap where the value can be one of multiple types?

I want to make a JSON object which includes multiple types.我想制作一个包含多种类型的 JSON 对象。 Here's the structure:这是结构:

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

How can I make a HashMap which accepts all these types?如何制作接受所有这些类型的HashMap

I'm trying this:我正在尝试这个:

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();

I know that the hash map does not have enough type info, but I'm not sure how I can make it work.我知道哈希映射没有足够的类型信息,但我不确定如何使其工作。 I have tried setting an explicit type on item which was HashMap<&str, Encodable> but then it's just another error.我尝试在HashMap<&str, Encodable> item上设置显式类型HashMap<&str, Encodable>只是另一个错误。 What is the correct way to do this?这样做的正确方法是什么?

You should use an enum type as value in your HashMap .您应该在HashMap使用枚举类型作为值。 That enum needs to have a variant for each possible type (boolean, number, string, list, map...) and an associated value of appropriate type for each variant:该枚举需要为每种可能的类型(布尔值、数字、字符串、列表、映射...)提供一个变体,并为每个变体提供一个适当类型的关联值:

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

Fortunately, there already is an implementation of a JSON value type , part of the serde_json crate which is built on the serde crate.幸运的是,已经有一个 JSON value type 的实现,它是serde_json crate 的一部分,它构建在serde crate 上。

Here is how your code would look if you used the serde_json 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}}
}

Here is another approach that may be more palatable to you.这是另一种可能更适合您的方法。 The serde_json crate provides a way to construct serde_json::Value objects from JSON literals. serde_json crate提供了一种从 JSON 文字构造serde_json::Value对象的方法。 Your example would look like this:您的示例如下所示:

#[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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM