|
1 | 1 | use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; |
2 | 2 | use serde::{Deserialize, Deserializer}; |
| 3 | +use serde_json::Value; |
3 | 4 | use std::borrow::Cow; |
4 | 5 | use std::fmt; |
5 | 6 |
|
@@ -60,13 +61,11 @@ impl<'de> Deserialize<'de> for URLParameters { |
60 | 61 | out.0.push_str("[]"); |
61 | 62 | out.0.push('='); |
62 | 63 |
|
63 | | - let val = val.to_string(); |
64 | | - // Remove any surrounding quotes added by serde_json |
65 | | - out.encode_and_push(if val.starts_with("\"") && val.ends_with("\"") { |
66 | | - &val[1..val.len() - 1] |
67 | | - } else { |
68 | | - &val |
69 | | - }); |
| 64 | + let val = match val { |
| 65 | + Value::String(s) => s, |
| 66 | + other => other.to_string(), |
| 67 | + }; |
| 68 | + out.encode_and_push(&val); |
70 | 69 | } |
71 | 70 | } else { |
72 | 71 | out.push_kv(&key, value); |
@@ -96,3 +95,30 @@ fn test_url_parameters_deserializer() { |
96 | 95 | "x=hello%20world&num=123&arr[]=1&arr[]=2&arr[]=3" |
97 | 96 | ); |
98 | 97 | } |
| 98 | + |
| 99 | +#[test] |
| 100 | +fn test_url_parameters_deserializer_special_chars() { |
| 101 | + use serde_json::json; |
| 102 | + let json = json!({ |
| 103 | + "chars": ["\n", " ", "\""], |
| 104 | + }); |
| 105 | + |
| 106 | + let url_parameters: URLParameters = serde_json::from_value(json).unwrap(); |
| 107 | + assert_eq!(url_parameters.0, "chars[]=%0A&chars[]=%20&chars[]=%22"); |
| 108 | +} |
| 109 | + |
| 110 | +#[test] |
| 111 | +fn test_url_parameters_deserializer_issue_879() { |
| 112 | + use serde_json::json; |
| 113 | + let json = json!({ |
| 114 | + "name": "John Doe & Son's", |
| 115 | + "items": [1, "item 2 & 3", true], |
| 116 | + "special_char": "%&=+ ", |
| 117 | + }); |
| 118 | + |
| 119 | + let url_parameters: URLParameters = serde_json::from_value(json).unwrap(); |
| 120 | + assert_eq!( |
| 121 | + url_parameters.0, |
| 122 | + "name=John%20Doe%20%26%20Son%27s&items[]=1&items[]=item%202%20%26%203&items[]=true&special%5Fchar=%25%26%3D%2B%20" |
| 123 | + ); |
| 124 | +} |
0 commit comments