如何使用 serde 将字符串键和数字或字符串值的映射反序列化为 HashMap<String, String>?

How to deserialize a map of string keys and numbers or string values as a HashMap<String, String> with serde?

我有一个级别 json,其中的值是 i32s、f32s 和 Strings。 如何将 json 反序列化为 HashMap<String, String>

{
    "key1": "value1",
    "key2": 0,
    "key3": 6.7
}

如何反序列化? serde 中有什么方法可以帮到您吗?

let json: HashMap<String, String>= serde_json::from_str(r#"{"key1": "value1", "key2": 0, "key3": 6.7}"#).unwrap();

编辑

我想知道 serde 是否提供了一种方法来避免由于额外迭代而产生的开销。

我们可以通过以下方式解决:

let str = r#"{"three": "123", "one": 1, "two": 12}"#;
    let map:HashMap<String,serde_json::Value> = serde_json::from_str(str).unwrap();
    let out_map:HashMap<String,String> = map.iter().map(|val| ( a.0.to_string() , a.1.to_string()) ) .collect();

如果您事先不知道有效的类型,您可以使用内置的 Value 数据结构。

Value表示JSON:

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

接下来你可以做:

use serde::{Deserialize, Serialize};
use serde_json::{Result, Value};

fn main() -> Result<()> {
    let s = r#"{"three": "2", "one": 1, "two": 12}"#;

    // Object({"one": Number(1), "three": String(2), "two": Number(12)})
    let data: Value = serde_json::from_str(&s)?;
    
    // OR
    {
       let data: HashMap<String, Value> = serde_json::from_str(&s)?;
    }
    println!("Hello {:?}", data.get("one"));
    Ok(())
}

您没有指定 Rust 字符串应包含的内容。此解决方案将使值部分与 JSON 中的完全相同,包括字符串周围的尾随数字和引号。这是 运行 此代码的结果:

[src/main.rs:15] map = {
    "key1": "\"value1\"",
    "key2": "0",
    "key3": "6.7",
    "key4": "0.000",
}
use serde::de::*;
use std::collections::HashMap;

fn main() {
    let j = r#"
    {
        "key1": "value1",
        "key2": 0,
        "key3": 6.7,
        "key4": 0.000
    }"#;

    let mut deser = serde_json::Deserializer::from_str(j);
    let map = deser_hashmap(&mut deser).unwrap();
    dbg!(map);
}

fn deser_hashmap<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
where
    D: Deserializer<'de>,
{
    struct MapVisitor;

    impl<'de> Visitor<'de> for MapVisitor {
        type Value = HashMap<String, String>;

        fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            formatter.write_str("a map")
        }

        fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
        where
            A: MapAccess<'de>,
        {
            let mut values = HashMap::new();

            // We use RawValue here to access the JSON value exactly as it is occuring in the input.
            while let Some((key, value)) = (access.next_entry())?
                .map(|(k, v): (String, &'de serde_json::value::RawValue)| (k, v.get().to_owned()))
            {
                values.insert(key, value);
            }

            Ok(values)
        }
    }

    let visitor = MapVisitor;
    deserializer.deserialize_map(visitor)
}

Code on Playground