用于解析JSON对象数组的正则表达式?

时间:2009-01-03 03:53:07

标签: c# .net regex json

我正在尝试将一组JSON对象解析为C#中的字符串数组。我可以从JSON对象中提取数组,但我无法将数组字符串拆分为单个对象的数组。

我所拥有的是这个测试字符串:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

现在我正在使用以下正则表达式将项目拆分为单个对象。现在他们是2个单独的正则表达式,直到我用第二个修复问题:

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

arrayFinder正则表达式按我预期的方式工作,但由于我不明白的原因,arrayParser正则表达式根本不起作用。我想要它做的就是将各个项目拆分成自己的字符串,这样我得到一个这样的列表:

  

{id:0,name:"Lorem Ipsum"}
  {id:1,name:"Lorem Ipsum"}
  {id:2,name:"Lorem Ipsum"}

此列表是string[]数组还是GroupMatch集合无关紧要,但我对如何拆分对象感到困惑。使用上面声明的arrayParserjson字符串,我尝试过这个代码,我认为这样做没有运气:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

string array = arrayFinder.Match(json).Groups["items"].Value;
// At this point the 'array' variable contains: 
// {id:0,name:"Lorem Ipsum"},{id:1,name:"Lorem Ipsum"},{id:2,name:"Lorem Ipsum"}

// I would have expected one of these 2 lines to return 
// the array of matches I'm looking for
CaptureCollection c = arrayParser.Match(array).Captures;
GroupCollection g = arrayParser.Match(array).Groups;

任何人都可以看到它我做错了吗?我完全坚持这个。

5 个答案:

答案 0 :(得分:38)

平衡括号实际上是无法使用正则表达式处理的语言的教科书示例。 JSON基本上是平衡括号加上一堆其他东西,括号替换为parens。在hierarchy of formal languages中,JSON是一种无上下文的语言。正则表达式无法解析无上下文的语言。

有些系统提供正则表达式的扩展,有点处理平衡表达式。然而,它们都是丑陋的黑客,它们都是不可移植的,而且它们最终都是错误的工具。

在专业工作中,您几乎总是使用现有的JSON解析器。如果你想为了教育目的而自己动手,那么我建议从一个支持+ - * /()的简单算术语法开始。 (JSON有一些逃避规则,虽然不复杂,但会使你的第一次尝试比它需要的更难。)基本上,你需要:

  1. 将语言分解为符号字母
  2. 根据识别语言的符号编写无上下文语法
  3. 将语法转换为Chomsky普通形式,或接近足以使第5步轻松
  4. 编写将原始文本转换为输入字母的词法分析器
  5. 编写一个递归下降解析器,它获取词法分析器的输出,解析它并产生某种输出
  6. 这是几乎所有大学的典型的第三年CS任务。

    下一步是找出在递归解析器中触发堆栈溢出所需的JSON字符串的复杂程度。然后看看可以编写的其他类型的解析器,你就会明白为什么必须在现实世界中解析无上下文语言的人使用像yacc或antlr这样的工具而不是手工编写解析器。

    如果这比您正在寻找的学习更多,那么您应该随意使用现成的JSON解析器,以满足您学到的重要且有用的东西:正则表达式的限制。

答案 1 :(得分:11)

  

平衡括号实际上是无法用正则表达式处理的语言的教科书示例

bla bla bla ... 看看这个:

arrayParser = "(?<Key>[\w]+)":"?(?<Value>([\s\w\d\.\\\-/:_]+(,[,\s\w\d\.\\\-/:_]+)?)+)"?

这对我有用

如果您想匹配空值,请将上一个'+'更改为'*'

答案 2 :(得分:6)

您使用的是.NET 3.5吗?如果是这样,您可以使用DataContractJsonSerializer来解析它。没有理由自己这样做。

如果您不使用.NET 3.5,则可以使用Jayrock

答案 3 :(得分:1)

public Dictionary<string, string> ParseJSON(string s)
{
    Regex r = new Regex("\"(?<Key>[\\w]*)\":\"?(?<Value>([\\s\\w\\d\\.\\\\\\-/:_\\+]+(,[,\\s\\w\\d\\.\\\\\\-/:_\\+]*)?)*)\"?");
    MatchCollection mc = r.Matches(s);

    Dictionary<string, string> json = new Dictionary<string, string>();

    foreach (Match k in mc)
    {
        json.Add(k.Groups["Key"].Value, k.Groups["Value"].Value);

    }
    return json;
}

此函数实现Lukasz正则表达式。我只添加了include + char到值组(因为我使用它来解析实时连接身份验证令牌)

答案 4 :(得分:0)

JSON通常不能用正则表达式解析(JSON的某些非常简化的变体可以,但是它们不是JSON而是其他东西)。

您需要一个实际的解析器才能正确解析JSON。

无论如何,你为什么要尝试解析JSON?有很多库可以为你做,并且比你的代码要好得多。为什么重新发明轮子,当拐角处有一个轮子工厂,门上有FOSS这个词?