【问题标题】:How to deserialize a map of string keys and numbers or string values as a HashMap<String, String> with serde?如何使用 serde 将字符串键和数字或字符串值的映射反序列化为 HashMap<String, String>?
【发布时间】:2021-06-27 11:24:32
【问题描述】:

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

{
    "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 是否提供了一种方法,比如一个标志来避免额外迭代导致的开销。

【问题讨论】:

  • 由于您删除了您的other question,而不是允许它被标记为重复(重复也不错!),这里是the solution
  • @Shepmaster 非常感谢!

标签: json rust serde


【解决方案1】:

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

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

【讨论】:

  • 不知道有没有serde提供的方式像个flag
【解决方案2】:

你没有指定 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

【讨论】:

    【解决方案3】:

    如果您事先不知道值的类型,可以使用内置的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(())
    }
    
    

    【讨论】:

      猜你喜欢
      • 2016-01-25
      • 1970-01-01
      • 2022-01-13
      • 2017-08-02
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      相关资源
      最近更新 更多