How do I decode a URL and get the query string as a HashMap?
There are a few steps involved:
The
.query_pairs()
method will give you an iterator over pairs ofCow<str>
.Calling
.into_owned()
on that will give you an iterator overString
pairs instead.This is an iterator of
(String, String)
, which is exactly the right shape to.collect()
into aHashMap<String, String>
.
Putting it together:
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");
Note that you need a type annotation on the hash_query
—since .collect()
is overloaded, you have to tell the compiler which collection type you want.
If you need to handle repeated or duplicate keys, try the multimap
crate:
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"]));
The other answer is good, but I feel that this is something that should be more straightforward, so I wrapped it in a function:
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(())
}
Alternatively, I found another crate that does this for you:
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