解析“querystring”格式数据的最简单方法

34

使用以下代码:

string q = "userID=16555&gameID=60&score=4542.122&time=343114";

最简单的方法是什么?如果可能的话,最好不要编写自己的解析器。我正在寻找与 Request.querystring ["gameID"] 具有相同功能的东西。

8个回答

88

非常简单... 使用 HttpUtility.ParseQueryString 方法

未经测试,但这应该可以工作:

var qs = "userID=16555&gameID=60&score=4542.122&time=343114";
var parsed = HttpUtility.ParseQueryString(qs);
var userId = parsed["userID"]; 
//  ^^^^^^ Should be "16555".  Note this will be a string of course.

2
谢谢!看起来不错,但我在解码MSDN页面上提供的可怕示例时遇到了麻烦,一旦我有了var q = HttpUtility.ParseQueryString("?userID=16555&gameID=60&score=4542.122&time=343114");,我该如何检索特定值? - Tom Gullen
1
我找不到 System.Net.HttpUtility 在 Core 1.0 框架中。 - Aakash
1
似乎他们已经移除了它。请参考这里的答案获取解决方案:https://dev59.com/_l0a5IYBdhLWcg3wva16 - Chris Shain
@GSerg 如果你在查询字符串中有1025个键,我会认为你有更大的问题。 - Chris Shain
@ChrisShain 好的,比如有一个Paypal API,它返回交易数据作为一大串键值对的url编码字符串。它很容易超过1024个字符。 - GSerg
显示剩余2条评论

23

你可以使用LINQ像这样做。

string query = "id=3123123&userId=44423&format=json";

Dictionary<string,string> dicQueryString = 
        query.Split('&')
             .ToDictionary(c => c.Split('=')[0],
                           c => Uri.UnescapeDataString(c.Split('=')[1]));

string userId = dicQueryString["userID"];

编辑

如果您可以使用HttpUtility.ParseQueryString,那么它将更加直接并且不像LinQ那样区分大小写。


1
这在特定情况下是有效的,但它不是通用解决方案,因为它不执行百分比解码。 - Francis Avila
2
如果您需要在System.Web上下文之外解析查询字符串,则这是一个不错的解决方案。 - Rick Strahl
7
当查询字符串为a=1&a=2&a=3或者a=1;a=2;a=3时会发生什么?这是有效的,使用HttpUtility.ParseQueryString进行处理可以解决这些和其他奇怪的情况。 - Jim Mischel
我来到这里是因为HttpUtility.ParseQueryString()执行了解码。这个解决方案对我很有效。 - kennydust
建议使用.ToLookup而不是.ToDictionary来处理“重复键”。 - drzaus
显示剩余2条评论

7

正如之前每个回答中所提到的,在你可以添加依赖于System.Web库的情况下,使用HttpUtility.ParseQueryString是有意义的。(有关参考资料,请参阅Microsoft 参考源代码)。但是,如果这不可能,我想提出以下修改建议,以解决评论中提出的许多问题(例如大小写敏感性和重复键):Adil's的答案。

var q = "userID=16555&gameID=60&score=4542.122&time=343114";
var parsed = q.TrimStart('?')
    .Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
    .Select(k => k.Split('='))
    .Where(k => k.Length == 2)
    .ToLookup(a => a[0], a => Uri.UnescapeDataString(a[1])
      , StringComparer.OrdinalIgnoreCase);
var userId = parsed["userID"].FirstOrDefault();
var time = parsed["TIME"].Select(v => (int?)int.Parse(v)).FirstOrDefault();

忽略单个参数,有时也可能出现:arg1&arg2&arg3 - jsuddsjr

5
如果你想避免使用 HttpUtility.ParseQueryString 需要的 System.Web 依赖,你可以使用在 System.Net.Http 中找到的 Uri 扩展方法 ParseQueryString
请注意,你需要将响应正文转换为有效的 Uri,以便 ParseQueryString 起作用。
还请注意,在 MSDN 文档中,该方法是 Uri 类的扩展方法,因此你需要引用 System.Net.Http.Formatting 程序集(在 System.Net.Http.Formatting.dll 中)。我尝试通过名为“System.Net.Http.Formatting”的 nuget 包安装它,它运行良好。
string body = "value1=randomvalue1&value2=randomValue2";

// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();

不确定这是否有效...当我尝试这样做时,Uri没有ParseQueryString方法附加到它上面,我的代码:var collection = new System.Uri(url).ParseQueryString(); - Trevor Hart
@TrevorHart 你确定已经添加了 System.Net.Http 的引用并且添加了 System.Net.Http 命名空间吗? - Amadeus Sanchez
1
我最终只能自己编写解析器。 - Trevor Hart

4

这个怎么样

using System.Text.RegularExpressions;

// query example
//   "name1=value1&name2=value2&name3=value3"
//   "?name1=value1&name2=value2&name3=value3"
private Dictionary<string, string> ParseQuery(string query)
{
    var dic = new Dictionary<string, string>();
    var reg = new Regex("(?:[?&]|^)([^&]+)=([^&]*)");
    var matches = reg.Matches(query);
    foreach (Match match in matches) {
        dic[match.Groups[1].Value] = Uri.UnescapeDataString(match.Groups[2].Value);
    }
    return dic;
}

谢谢!它是否支持单个参数,如@jsuddsjr的评论所提到的? 忽略单个参数,有时也会出现: arg1&arg2&arg3 - gregn3

2

1

System.Net.Http的ParseQueryString扩展方法对我很有用。我正在使用OData查询选项并尝试解析一些自定义参数。

options.Request.RequestUri.ParseQueryString();

似乎给了我我需要的东西。

0

只要你在 Web 应用程序中或不介意包含 System.Web 依赖项,HttpUtility.ParseQueryString 就可以工作。另一种方法是:

// NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(queryString);

NameValueCollection nameValueCollection = new NameValueCollection();
string[] querySegments = queryString.Split('&');
foreach(string segment in querySegments)
{
   string[] parts = segment.Split('=');
   if (parts.Length > 0)
   {
      string key = parts[0].Trim(new char[] { '?', ' ' });
      string val = parts[1].Trim();

      nameValueCollection.Add(key, val);
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接