Как мне декодировать URL и получить строку запроса в виде HashMap?
У меня есть такой URL:
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
3 ответа
Есть несколько шагов:
.query_pairs()
метод даст вам итератор по парамCow<str>
,призвание
.into_owned()
на что даст вам итераторString
пары вместоЭто итератор
(String, String)
, которая является точно правильной формы.collect()
вHashMap<String, String>
,
Собираем это вместе:
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()
перегружен, вы должны указать компилятору, какой тип коллекции вы хотите.
Другой ответ хорош, но я считаю, что это должно быть проще, поэтому я заключил его в функцию:
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(())
}
Вот решение для разбора уже декодированной строки запроса из&str
вHashMap<String, String>
используя только стандартную библиотеку Rust, без необходимости использования внешних крейтов:
use std::collections::HashMap;
fn parse_query(query: &str) -> HashMap<String, String> {
query
.split('&')
.filter_map(|s| {
s.split_once('=')
.and_then(|t| Some((t.0.to_owned(), t.1.to_owned())))
})
.collect()
}