13

我有一个这样的网址:

http%3A%2F%2Fexample.com%3Fa%3D1%26b%3D2%26c%3D3

我用它解析hyper::Url::parse并获取查询字符串:

let parsed_url = hyper::Url::parse(&u).unwrap();
let query_string = parsed_url.query();

但它给了我作为字符串的查询。我想将查询字符串作为HashMap. 像这样的东西:

// some code to convert query string to HashMap
hash_query.get(&"a"); // eq to 1
hash_query.get(&"b"); // eq to 2
4

2 回答 2

19

涉及几个步骤:

  • .query_pairs()方法将为您提供一个迭代器对Cow<str>.

  • 调用.into_owned()它会给你一个迭代器String而不是对。

  • 这是一个 的迭代器(String, String),它恰好是.collect()转换为的正确形状HashMap<String, String>

把它放在一起:

use std::collections::HashMap;
let parsed_url = Url::parse("http://example.com/?a=1&b=2&c=3").unwrap();
let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();
assert_eq!(hash_query.get("a"), "1");

请注意,您需要在 - 上添加类型注释,hash_query因为.collect()已重载,您必须告诉编译器您想要哪种集合类型。

如果您需要处理重复或重复的键,请尝试使用multimapcrate:

use multimap::MultiMap;
let parsed_url = Url::parse("http://example.com/?a=1&a=2&a=3").unwrap();
let hash_query: MultiMap<_, _> = parsed_url.query_pairs().into_owned().collect();
assert_eq!(hash_query.get_vec("a"), Some(&vec!["1", "2", "3"]));
于 2017-04-07T08:38:16.280 回答
1

另一个答案很好,但我觉得这应该更直接,所以我将它包装在一个函数中:

use {
   std::collections::HashMap,
   url::Url
};

fn query(u: Url) -> HashMap<String, String> {
   u.query_pairs().into_owned().collect()
}

fn main() -> Result<(), url::ParseError> {
   let u = Url::parse("http://stackoverflow.com?month=May&day=Friday")?;
   let q = query(u);
   println!("{:?}", q);
   Ok(())
}

或者,我找到了另一个可以为您执行此操作的板条箱:

use auris::URI;

fn main() -> Result<(), auris::ParseError> {
   let s = "http://stackoverflow.com?month=May&day=Friday";
   let u: URI<String> = s.parse()?;
   println!("{:?}", u.qs); // Some({"month": "May", "day": "Friday"})
   Ok(())
}

https://docs.rs/auris

于 2021-02-02T16:28:53.027 回答