这是我的扩展方法。它支持嵌套。 Javascript 对象表示为 Dictionary,而 javascript 数组表示为 IEnumerable。
public static class ToQueryStringExtension
{
public static string ToQueryString(this Dictionary<string, object> obj)
{
if (obj == null) return "";
string query = "";
bool first = true;
Dictionary<string, List<string>> data = ToQueryStringHelper(obj);
foreach (KeyValuePair<string, List<string>> kvp in data)
{
string keyUrlencoded = UpperCaseUrlEncode(kvp.Key);
foreach (string ele in kvp.Value)
{
if (first) first = false;
else query += "&";
query += keyUrlencoded + ele;
}
}
return query;
}
private static Dictionary<string, List<string>> ToQueryStringHelper(Dictionary<string, object> obj)
{
Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
foreach (KeyValuePair<string, object> kvp in obj)
{
if (kvp.Value is Dictionary<string, object>)
{
Dictionary<string, List<string>> dataInner = ToQueryStringHelper((Dictionary<string, object>)kvp.Value);
if (dataInner.Count < 1) continue;
data.Add(kvp.Key, new List<string>());
foreach (KeyValuePair<string, List<string>> kvpInner in dataInner)
{
string keyUrlencoded = UpperCaseUrlEncode("[" + kvpInner.Key + "]");
foreach (string ele in kvpInner.Value)
{
data[kvp.Key].Add(keyUrlencoded + ele);
}
}
}
else if ((kvp.Value is IEnumerable) && !(kvp.Value is string))
{
Dictionary<string, object> objInner = new Dictionary<string, object>();
IEnumerable list = (IEnumerable)kvp.Value;
int inx = 0;
foreach (object ele in list)
{
objInner.Add(inx.ToString(), ele);
inx++;
}
Dictionary<string, List<string>> dataInner = ToQueryStringHelper(objInner);
if (dataInner.Count < 1) continue;
data.Add(kvp.Key, new List<string>());
foreach (KeyValuePair<string, List<string>> kvpInner in dataInner)
{
// index key can be removed in peripheral nodes
string keyUrlencoded = null;
if (kvpInner.Value.Count == 1 && kvpInner.Value[0].StartsWith("=")) keyUrlencoded = General.UpperCaseUrlEncode("[]");
else keyUrlencoded = UpperCaseUrlEncode("[" + kvpInner.Key + "]");
foreach (string ele in kvpInner.Value)
{
data[kvp.Key].Add(keyUrlencoded + ele);
}
}
}
else
{
// Optional check if peripheral value type is known.
//Type type = kvp.Value.GetType();
//if (!(kvp.Value is Decimal) && !(kvp.Value is string) && !(type.IsPrimitive)) throw new Exception("Unknown peripheral type.");
if (kvp.Value != null)
{
data.Add(kvp.Key, new List<string>());
data[kvp.Key].Add("=" + UpperCaseUrlEncode(kvp.Value.ToString()));
}
}
}
return data;
}
public static string UpperCaseUrlEncode(string s)
{
char[] temp = HttpUtility.UrlEncode(s).ToCharArray();
for (int i = 0; i < temp.Length - 2; i++)
{
if (temp[i] == '%')
{
temp[i + 1] = char.ToUpper(temp[i + 1]);
temp[i + 2] = char.ToUpper(temp[i + 2]);
}
}
return new string(temp);
}
}