搞定queryString


querystring字面上的意思就是查詢字符串,一般是對http請求所帶的數據進行解析。querystring模塊只提供4個方法:

  • querystring.parse
  • querystring.stringify
  • querystring.escape
  • querystring.unescape

這4個方法是相對應的。

首先,使用querystring模塊之前,需要require進來:

const querystring = require("querystring");

其次,就可以使用模塊下的方法了:

1 querystring.parse(str,separator,eq,options)

parse這個方法是將一個字符串反序列化為一個對象。

參數:

  • str指需要反序列化的字符串;
  • separator(可省)指用於分割str這個字符串的字符或字符串,默認值為"&";
  • eq(可省)指用於划分鍵和值的字符或字符串,默認值為"=";
  • options(可省)該參數是一個對象,里面可設置maxKeys和decodeURIComponent這兩個屬性:
  1. maxKeys:傳入一個number類型,指定解析鍵值對的最大值,默認值為1000,如果設置為0時,則取消解析的數量限制;
  2. decodeURIComponent:傳入一個function,用於對含有%的字符串進行解碼,默認值為querystring.unescape。在官方API的例子中,使用gbkDecodeURIComponent這個方法會報錯,顯示gbkDecodeURIComponent is no defined,這是因為在使用這個gbkDecodeURIComponent這個方法之前需要先進行定義。在API中也寫了Assuming gbkDecodeURIComponent function already exists...這句話的意思是”假設這個gbkDecodeURIComponent方法已經存在”。

例子1,querystring.parse

 1 querystring.parse("name=whitemu&sex=man&sex=women");
 2 /*
 3 return:
 4 { name: 'whitemu', sex: [ 'man', 'women' ] }
 5 */
 6 querystring.parse("name=whitemu#sex=man#sex=women","#",null,{maxKeys:2});
 7 /*
 8 return:
 9 { name: 'whitemu', sex: 'man' }
10 */

2 querystring.stringify(obj,separator,eq,options)

stringify這個方法是將一個對象序列化成一個字符串,與querystring.parse相對。

參數:

  • obj指需要序列化的對象
  • separator(可省)用於連接鍵值對的字符或字符串,默認值為"&";
  • eq(可省)用於連接鍵和值的字符或字符串,默認值為"=";
  • options(可省)傳入一個對象,該對象可設置encodeURIComponent這個屬性:

encodeURIComponent:值的類型為function,可以將一個不安全的url字符串轉換成百分比的形式,默認值為querystring.escape()。

例子2,querystring.stringify

querystring.stringify({name: 'whitemu', sex: [ 'man', 'women' ] });
/*
return:
'name=whitemu&sex=man&sex=women'
*/
querystring.stringify({name: 'whitemu', sex: [ 'man', 'women' ] },"*","$");
/*
return:
'name$whitemu*sex$man*sex$women'
*/

3 querystring.escape(str)

escape可使傳入的字符串進行編碼

例子3,querystring.escape

querystring.escape("name=慕白");
/*
return:
'name%3D%E6%85%95%E7%99%BD'
*/

4 querystring.unescape(str)

unescape方法可將含有%的字符串進行解碼

例子4,querystring.unescape

querystring.unescape('name%3D%E6%85%95%E7%99%BD');
/*
return:
'name=慕白'
*/

小結:

querystring這個模塊相對的還是比較簡單,僅有4個方法。

  • querystring.stringify序列化;
  • querystring.parse反序列化;
  • querystring.escape編碼;
  • querystring.unescape解碼;

進階版

可以寫一個函數,專門用於做轉換

 private object ConvertParameter(string name, object defaultValue, bool isRequired)

我們甚至還可以把它抽象出來一個方法。

提取抽象方法

用Attribute和反射的思想,首先給變量設置HttpQueryString的屬性,綁定上相應的QueryString,然后由Page基類來讀取相應的QueryString信息。

屬性這么寫(HttpQueryStringAttribute.cs):

[AttributeUsage(AttributeTargets.Field)] 
    
    public sealed class HttpQueryStringAttribute : Attribute { 
        private string _name; 
        private object _defaultValue; 
        private bool _isRequired; 
        
        
    public HttpQueryStringAttribute(string name) { 
            _name = name; 
            _defaultValue = null; 
            _isRequired = true; 
        }    
        
    public HttpQueryStringAttribute(string name, object defaultValue) { 
            _name = name; 
            _defaultValue = defaultValue; 
            _isRequired = false; 
        } 
    
    public string Name { 
            get { return _name; } 
        } 
        
    public object DefaultValue { 
            get { return _defaultValue; } 
        }
        
    public bool IsRequired 
        { 
            get { return _isRequired; } 
        } 
    } 

頁面基類是這樣的(PageBase.cs):

public class PageBase : Page 
    {
     protected override void OnLoad(System.EventArgs e) { 
            ParameterInitialize(); 
            base.OnLoad(e); 
        } 
    
    
    private void ParameterInitialize() { 
        Type type = this.GetType(); 
    
        FieldInfo[] fields = type.GetFields(); 

            foreach (FieldInfo field in fields) 
            {
                HttpQueryStringAttribute attribute = (HttpQueryStringAttribute)Attribute.GetCustomAttribute(field, typeof(HttpQueryStringAttribute)); 

                if (attribute != null) 
                { 
                    SetField(field, attribute); 
                } 
            } 
        }
        
    private void SetField(FieldInfo field, HttpQueryStringAttribute attribute) 
        {
            if (attribute.IsRequired) 
            { 
                if (Request.QueryString[attribute.Name] != null) 
                { 
                    SetFieldValue(field, this, attribute.Name, field.FieldType); 
                } 
                else 
                { 
                    throw new Exception(string.Format("Query string /"{0}/" is required", attribute.Name), new NullReferenceException()); 
                } 
            } 
            else 
            { 
                if (attribute.DefaultValue == null || field.FieldType == attribute.DefaultValue.GetType()) 
                { 
                    if (Request.QueryString[attribute.Name] == null || Request.QueryString[attribute.Name] == string.Empty) 
                    { 
                        field.SetValue(this, attribute.DefaultValue); 
                    } 
                    else 
                    { 
                        SetFieldValue(field, this, attribute.Name, field.FieldType); 
                    } 
                } 
                else 
                { 
                    throw new Exception(string.Format("Invalid default value of query string /"{0}/"({1})", attribute.Name, field.Name), new NullReferenceException()); 
                } 
            } 
        }
        
    private void SetFieldValue(FieldInfo field, object obj, string name, Type conversionType) { 
            try 
            { 
                field.SetValue(obj, Convert.ChangeType(Request.QueryString[name], conversionType)); 
            } 
            catch (Exception ex) 
            { 
                throw new Exception(string.Format("The given value of query string /"{0}/" can not be convert to {1}", name, conversionType), ex); 
            } 
        } 
    } 

在頁面里,這樣寫就OK了(Default.aspx.cs):

public partial class _Default : PageBase 
{ 
    [HttpQueryString("Name", "Anonymous")] 
    public string name; 
    
     [HttpQueryString("UserId")] 
    public int userId; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
        Response.Write(string.Format("Name is {0}<br/>", name)); 
        Response.Write(string.Format("UserId is {0}<br/>", userId)); 
    } 
} 

討論

根據定義的變量的數據類型自動轉換對應的QueryString,可以省去以后在頁面里處理Query String的代碼。

反過來想,QueryString 的處理沒必要上升到反射的高度,復雜的實現也許會喪失一定的靈活性。比如我某個值忽然要改為從 Form 里面得到呢?從 Session 得到呢?這時候就可以比較出哪種做法更適合敏捷的適應需求。

頁面里的 QueryString 的處理,之所以大家都很痛恨手工寫編碼,無非是因為這么幾點:

  1. 需要判斷是否 == null 才敢用 .ToString(), 很不爽。稍微不注意,就會拋出異常導致頁面錯誤。
  2. 整形,double 等值類型從 QueryString 里面獲取的時候,不知道是否為合法的數值,因此 Parse 的時候總是要寫重復的處理異常的代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM