diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/introduction.rs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/examples/introduction.rs b/examples/introduction.rs new file mode 100644 index 0000000..9d949b4 --- /dev/null +++ b/examples/introduction.rs @@ -0,0 +1,131 @@ +extern crate csv; +extern crate rand; +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_qs as qs; +extern crate serde_urlencoded as urlencoded; + +use rand::Rng; +use std::collections::HashMap; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +struct Address { + city: String, + postcode: String, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +struct QueryParams { + id: u8, + name: String, + address: Address, + phone: u32, + user_ids: Vec<u8>, +} + + +fn main() { + // Encodes as: + // "user_ids%5B3%5D=4&user_ids%5B2%5D=3&address%5Bcity%5D=Carrot+City&\ + // id=42&address%5Bpostcode%5D=12345&name=Acme&user_ids%5B0%5D=1&\ + // phone=12345&user_ids%5B1%5D=2" + let example_params = QueryParams { + id: 42, + name: "Acme".to_string(), + phone: 12345, + address: Address { + city: "Carrot City".to_string(), + postcode: "12345".to_string(), + }, + user_ids: vec!(1,2,3,4), + }; + + // Naive approach: manually parameters in a map. Painful. + let mut map = HashMap::<&str, &str>::new(); + map.insert("id", "42"); + map.insert("name", "Acme"); + map.insert("phone", "12345"); + map.insert("address[city]", "Carrot City"); + map.insert("address[postcode]", "12345"); + map.insert("user_ids[0]", "1"); + map.insert("user_ids[1]", "2"); + map.insert("user_ids[2]", "3"); + map.insert("user_ids[3]", "4"); + + // Note this will be in some random order due to ordering of keys in map. + let encoded = qs::to_string(&map).unwrap(); + println!("`serde_qs` to_string for map:\n\t{}", encoded); + + // In this form, can also simply use `serde_urlencoded`: + let encoded = urlencoded::to_string(&map).unwrap(); + println!("`serde_urlencoded` to_string for map:\n\t{}", encoded); + + // Given this encoded string, you can recover the original map + // as a list of pairs using serde_urlencoded: + let pairs: Vec<(String, String)> = urlencoded::from_str(&encoded).unwrap(); + println!("`serde_urlencoded` from_str to pairs:\n\t{:?}", pairs); + + // However, the best way is to use serde_qs to deserialize the entire thing + // into a struct: + let params: QueryParams = qs::from_str(&encoded).unwrap(); + assert_eq!(params, example_params); + println!("`serde_qs` from_str to struct:\n\t{:?}", params); + + // Similarly, we can serialize this structure using `serde_qs`: + let encoded = qs::to_string(¶ms).unwrap(); + println!("`serde_qs` to_string for struct:\n\t{:?}", encoded); + + // One nice feature is that this gives deterministic encodings: + let encoded2 = qs::to_string(¶ms).unwrap(); + assert_eq!(encoded, encoded2); + + // An advantage of `serde_qs` for deserializing, is that it is robust against + // different orderings of inputs: + + let mut inputs = vec!["id=42", + "name=Acme", + "phone=12345", + "address[city]=Carrot+City", + "address[postcode]=12345", + "user_ids[0]=1", + "user_ids[1]=2", + "user_ids[2]=3", + "user_ids[3]=4" + ]; + + let mut rng = rand::thread_rng(); + for _ in 0..10 { + let mut acc = String::new(); + rng.shuffle(&mut inputs); + for input in &inputs { + acc += input; + acc += "&"; + } + // remove trailing character + acc.pop(); + let params: QueryParams = qs::from_str(&acc).unwrap(); + assert_eq!(params, example_params); + } + + // By default, `serde_qs` uses arrays with indices to denote position. + // However, if omitted, will use input order: + let encoded = "id=42&name=Acme&phone=12345&address[city]=Carrot+City&\ + address[postcode]=12345&\ + user_ids[]=1&\ + user_ids[]=2&\ + user_ids[]=3&\ + user_ids[]=4"; + let params: QueryParams = qs::from_str(encoded).unwrap(); + assert_eq!(params, example_params); + + // Indices do not necessarily need to be continuous: + let encoded = "id=42&name=Acme&phone=12345&address[city]=Carrot+City&\ + address[postcode]=12345&\ + user_ids[1]=2&\ + user_ids[0]=1&\ + user_ids[12]=3&\ + user_ids[512]=4"; + let params: QueryParams = qs::from_str(encoded).unwrap(); + assert_eq!(params, example_params); +}
\ No newline at end of file |