代码之家  ›  专栏  ›  技术社区  ›  Dan Herbert

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

  •  11
  • Dan Herbert  · 技术社区  · 16 年前

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

    arrayFinder regex的工作方式与我期望的一样,但由于我不理解的原因,它的 arrayParser 正则表达式根本不起作用。我想让它做的就是将各个项目拆分为它们自己的字符串,这样我就可以得到如下列表:

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

    此列表是否为 string[] 数组或 Group Match 收集不重要,但我很困惑如何分割对象。使用 arrayParser json

    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 回复  |  直到 16 年前
        1
  •  39
  •   user51099    16 年前

    平衡圆括号实际上是一种无法用正则表达式处理的语言的教科书示例。JSON本质上是平衡的括号加上一堆其他东西,大括号被paren替换。在 hierarchy of formal languages ,JSON是一种上下文无关语言。正则表达式无法分析上下文无关语言。

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

    1. 将语言分解为符号的字母表
    2. 根据识别语言的符号编写上下文无关语法
    3. 编写一个lexer,将原始文本转换为输入字母表
    4. 编写一个递归下降解析器,它接受lexer的输出,对其进行解析,并生成某种类型的输出

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

    如果这比你想要的要多,那么你应该可以随意使用现成的JSON解析器,因为你已经学到了一些重要而有用的东西:正则表达式的限制。

        2
  •  12
  •   Lukasz Lukasz    15 年前

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

    呜呜呜呜。。。 看看这个:

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

    这对我有用

    如果要匹配空值,请将最后一个“+”更改为“*”

        3
  •  6
  •   casperOne    13 年前

    DataContractJsonSerializer 来分析这一点。没有理由自己做这件事。

    如果您没有使用.NET3.5,您可以使用 Jayrock .

        4
  •  2
  •   Брайков    13 年前
    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正则表达式。我只将inclide+char添加到值组(因为我使用它来解析live connect身份验证令牌)

        5
  •  0
  •   yfeldblum    16 年前

    不管怎样,你为什么要解析JSON呢?有许多库可以为您完成这项工作,而且比您的代码要好得多。当拐角处有一家车轮工厂,门上写着FOSS字样时,为什么要重新发明车轮?