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

xzlaal3s  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(221)

我想创建一个包含多种类型的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();

我知道散列Map没有足够的类型信息,但我不确定如何才能使它工作。我曾尝试在item上设置一个显式类型,它是HashMap<&str, Encodable>,但它只是另一个错误。正确的方法是什么?

sxissh06

sxissh061#

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

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

幸运的是,已经有了an implementation of a JSON value typeserde_json机箱的一部分,它是在serde机箱上构建的。
下面是使用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}}
}
s1ag04yj

s1ag04yj2#

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

use serde_json::json; 

fn main() {
    let item = json!({
        "key1": "value",
        "key2": ["val", "val", "val"],
        "key3": { "keyX": 12 }
    });

    let response = serde_json::to_string(&item).unwrap();
}

相关问题