如何使用 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
,其中的值是 i32
s、f32
s 和 String
s。
如何将 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)
}
我有一个级别 json
,其中的值是 i32
s、f32
s 和 String
s。
如何将 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)
}