解析逗号分隔的键值对

时间:2017-06-22 19:19:08

标签: 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"

我想把它变成KeyValuePair

由于

,解析这些数据很困难
  • 仅当键和值包含非字母数字字符
  • 时才会引用它们
  • 键和值可以包含逗号,(转义)双引号和等号符号

我有什么选择来处理这个?我已经尝试过CSV库,但结果却不正确。

2 个答案:

答案 0 :(得分:1)

我听过很多人说:如果用正则表达式解决问题,你就会遇到两个问题。哦,好吧......如果你不想写自己的解析器...这个小怪物效果很好:

   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();
        }
    }

答案 1 :(得分:0)

此代码应该完成这项工作:

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();
    }
}