今天遇到一個需求,需要處理通過介面傳過來的一個引數,引數內容為一個拼接好的Url地址,且該地址還會攜帶了一些額外的引數,包括但不限於數字,字串,json串。樣例如下:
http://www.cplemom.com/?url=https://www.cnblogs.com/cplemom/?id=15&data={"id":12,"name":"今天天氣不錯"}
現在的問題就是,我需要將url引數中的data值的json中的id修改為url引數中id的值,然後再拼接成完整的url去獲取資料。簡單來說就是將url進行如下改變,現在問題的重點就在於如何根據url獲取對應的引數值了。
//處理前
https://www.cnblogs.com/cplemom/?id=15&data={"id":12,"name":"今天天氣不錯"}
//處理後
https://www.cnblogs.com/cplemom/?id=15&data={"id":15,"name":"今天天氣不錯"}
Url編碼
這裡插一句,在將url作為引數進行請求的時候,需要注意一些特殊字元(比如 ? "" /
等)對請求的影響,特別是傳送Get請求的時候。可以在傳送請求前,先對url進行編碼處理。
encodeURIComponent(url) //js
HttpUtility.UrlEncode(url) //C#
url.QueryEscape(url) //Go
獲取Url引數
仔細思考了下,解析url獲取引數的也無非通過分割關鍵字元來實現。區別就是分割字元的方式是通過正則匹配或者遍歷字元罷了。下面就介紹框架帶的方法,然後通過總結一些規律,最後自己實現一個方法。
我知道肯定有很多朋友經常使用HttpUtility
類中的UrlEncode/UrlDecode
方法,其實該類還有一個ParseQueryString
方法,用來解析url引數。該方法需要傳入url引數部分字串,然後返回一個NameValueCollection
物件(以key/value的形式記錄了所有引數)。
string url = "https://www.cnblogs.com/cplemom/?id=15&data={'id':12,'name':'今天天氣不錯'}";
var uri = new Uri(url);
var collection= HttpUtility.ParseQueryString(uri.Query);//預設採用UTF-8編碼,當然也可以傳入特定編碼進行解析
//var collection= HttpUtility.ParseQueryString(uri.Query,Encoding.ASCII);
Console.WriteLine(collection["data"]);//輸出結果: {'id':12,'name':'今天天氣不錯'}
該方法有幾個要注意的點
uri.Query
是?開頭的,但是在轉為鍵值對以後被自動過濾掉了,且只會過濾一個?字元- 引數內容會自動使用UTF-8解碼
- 對於傳遞的陣列引數(
?ids=1&ids=2
),會通過,
拼接 - 在引數字元中通過&劃分後,只會把第一個=前的字串作為key
基於上述一些要求就可以自己寫一個解析引數的方式了。
public static Dictionary<string, string> ParseQueryString(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url");
}
var uri = new Uri(url);
if (string.IsNullOrWhiteSpace(uri.Query))
{
return new Dictionary<string, string>();
}
//1.去除第一個前導?字元
var dic = uri.Query.Substring(1)
//2.通過&劃分各個引數
.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
//3.通過=劃分引數key和value,且保證只分割第一個=字元
.Select(param => param.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries))
//4.通過相同的引數key進行分組
.GroupBy(part => part[0], part => part.Length > 1 ? part[1] : string.Empty)
//5.將相同key的value以,拼接
.ToDictionary(group => group.Key, group => string.Join(",", group));
return dic;
}
總結
總體來說這只是一個小小的功能點,往往框架本身就幫我們封裝好了解析url獲取引數的方法,但是自己去實現的時候,可能就會有這樣那樣的情況沒有考慮到。最後如果有遇到相似需求的朋友,我建議還是用HttpUtility.ParseQueryString()
吧~~~