C# 解析逗号分隔的键值对
我有一个HTTP请求(授权)标头中的数据,该标头类似于以下内容:C# 解析逗号分隔的键值对,c#,wcf,parsing,deserialization,C#,Wcf,Parsing,Deserialization,我有一个HTTP请求(授权)标头中的数据,该标头类似于以下内容: name="Dave O'Connel", "e-mail"="dave@mailinator.com", epoch=1498158305, "other value"="some arbitrary\" text, with comma = and equals symbol" 我想把它做成一对钥匙 由于以下原因,很难解析此数据: 键和值仅在包含非字母数字字符时才被引用 键和值可以包含逗号、(转义)双引号和等于符号 我有
name="Dave O'Connel", "e-mail"="dave@mailinator.com", epoch=1498158305, "other value"="some arbitrary\" text, with comma = and equals symbol"
我想把它做成一对钥匙
由于以下原因,很难解析此数据:
- 键和值仅在包含非字母数字字符时才被引用
- 键和值可以包含逗号、(转义)双引号和等于符号
我有什么办法来处理这个问题?我尝试了CSV库,但结果不正确。这段代码应该可以完成这项工作:
class Program
{
static string Preprocess(string s)
{
bool esc = false, quoted = false;
StringBuilder sb = new StringBuilder();
foreach (var c in s)
{
if (c == '\\' && !esc)
esc = true;
else
{
if (c == '\"' && !esc)
quoted = !quoted;
else
{
if (c == '=' && quoted)
sb.Append('~');
else if (c == ',' && quoted)
sb.Append(';');
else
sb.Append(c);
}
esc = false;
}
}
return sb.ToString();
}
static string Postprocess(string s)
{
return s.Replace('~', '=').Replace(';', ',');
}
static Dictionary<string, string> MakeKeyValueList(string str)
{
var dict = new Dictionary<string, string>();
foreach (var kvp in Preprocess(str).Split(','))
{
string[] kv = kvp.Split(new char[] { '=' }, 2);
if (kv.Length == 2)
dict[Postprocess(kv[0]).Trim()] = Postprocess(kv[1]).Trim();
}
return dict;
}
static void Main(string[] args)
{
var dict = MakeKeyValueList("name=\"Dave O'Connel\", \"e-mail\"=\"dave@mailinator.com\", epoch=1498158305, \"other value\"=\"some arbitrary\\\" text, with comma = and equals symbol\"");
foreach (var kvp in dict)
Console.WriteLine(kvp.ToString());
Console.ReadKey();
}
}
类程序
{
静态字符串预处理(字符串s)
{
bool-esc=false,引号=false;
StringBuilder sb=新的StringBuilder();
foreach(s中的变量c)
{
如果(c=='\\'&&&!esc)
esc=真;
其他的
{
如果(c=='\'&&!esc)
quoted=!quoted;
其他的
{
if(c=='='&"e)
某人附加(“~”);
else if(c==','&"e)
某人附加(“;”);
其他的
sb.附加(c);
}
esc=假;
}
}
使某人返回字符串();
}
静态字符串后处理(字符串s)
{
返回s.Replace(“~”,“=”).Replace(“;”,“,”);
}
静态字典makeyValueList(字符串str)
{
var dict=新字典();
foreach(预处理中的var kvp(str).Split(','))
{
字符串[]kv=kvp.Split(新字符[]{'='},2);
如果(千伏长度==2)
dict[Postprocess(kv[0]).Trim()]=后处理(kv[1]).Trim();
}
返回命令;
}
静态void Main(字符串[]参数)
{
var dict=MakeKeyValueList(“姓名=\“Dave O'Connel\”,\“电子邮件=”dave@mailinator.com\“,epoch=1498158305,\”其他值\“=”一些任意\\”文本,带逗号=和等于符号\”);
foreach(dict中的var kvp)
Console.WriteLine(kvp.ToString());
Console.ReadKey();
}
}
我听很多人说:如果你用正则表达式解决一个问题,你就有两个问题。哦,好吧。。。如果您不想编写自己的解析器。。。这个小怪物工作得很好:
public class Program
{
static void Main(string[] args)
{
Regex regex = new Regex("^(?:(?:[, ]+)?(?\'q\'\")?(?\'key\'[^=\"]*?)(?:\\k\'q\'(?\'-q\'))?=(?\'q\'\")?(?\'value\'(?:[^\"]|(?<=\\\\)\")*)(?:\\k\'q\'(?\'-q\'))?)*(?(q)(?!))$", RegexOptions.Compiled);
string s = "name=\"Dave O\'Connel\", \"e-mail\"=\"dave@mailinator.com\", epoch=1498158305, \"other value\"=\"some arbitrary\\\" text, with comma = and equals symbol\"";
Match match = regex.Match(s);
if (match.Success)
{
var keys = match.Groups["key"].Captures;
var values = match.Groups["value"].Captures;
for (int i = 0; i < keys.Count; i++)
{
Console.WriteLine(keys[i] + " = " + values[i]);
// this prints:
// name = Dave O'Connel
// e-mail = dave@mailinator.com
// epoch = 1498158305,
// other value = some arbitrary\" text, with comma = and equals symbol
}
}
Console.ReadLine();
}
}
公共类程序
{
静态void Main(字符串[]参数)
{
正则表达式正则表达式=新正则表达式(“^(?:(?:[,]+)?(?\'q\'”)(?\'key\'[^=\']*?)(?:\\k\'q\'(?\'-q\'))?=(?\'q\'”)(?\'value\'(?:[^\”)|(?您可以修改从中获取数据的服务器?如果是,最好的解决方案是规范化服务器的响应。@S.Petrosov它实际上已经规范化了。所有文本值都被引用,字段中的引号都被转义。带有特殊字符的键值也被引用。这非常感谢。我甚至不打算尝试去理解正则表达式的e!我你想我可以为你剖析它并解释各个部分。而且,我相信有更好正则表达式技能的人可以用更短的方式重写它。。。