pyparsing:示例JSON解析器因dicts列表而失败

时间:2014-02-27 21:49:56

标签: python json parsing pyparsing

所有

我正在尝试了解如何使用pyparsing处理Dicts列表。我已经回到了example JSON parser的最佳实践,但我发现它也无法处理一系列的决定!

考虑以下内容(这是股票示例JSON解析器,但删除了一些注释,而我的测试用例而不是默认值):

#!/usr/bin/env python2.7

from pyparsing import *

TRUE = Keyword("true").setParseAction( replaceWith(True) )
FALSE = Keyword("false").setParseAction( replaceWith(False) )
NULL = Keyword("null").setParseAction( replaceWith(None) )

jsonString = dblQuotedString.setParseAction( removeQuotes )
jsonNumber = Combine( Optional('-') + ( '0' | Word('123456789',nums) ) +
                    Optional( '.' + Word(nums) ) +
                    Optional( Word('eE',exact=1) + Word(nums+'+-',nums) ) )

jsonObject = Forward()
jsonValue = Forward()
jsonElements = delimitedList( jsonValue )
jsonArray = Group(Suppress('[') + Optional(jsonElements) + Suppress(']') )
jsonValue << ( jsonString | jsonNumber | Group(jsonObject)  | jsonArray | TRUE | FALSE | NULL )
memberDef = Group( jsonString + Suppress(':') + jsonValue )
jsonMembers = delimitedList( memberDef )
jsonObject << Dict( Suppress('{') + Optional(jsonMembers) + Suppress('}') )

jsonComment = cppStyleComment
jsonObject.ignore( jsonComment )

def convertNumbers(s,l,toks):
    n = toks[0]
    try:
        return int(n)
    except ValueError, ve:
        return float(n)

jsonNumber.setParseAction( convertNumbers )

if __name__ == "__main__":
    testdata = """
[ { "foo": "bar", "baz": "bar2" },
  { "foo": "bob", "baz": "fez" } ]
    """
    results = jsonValue.parseString(testdata)
    print "[0]:", results[0].dump()
    print "[1]:", results[1].dump()

这是有效的JSON,但尝试索引到第二个预期的数组元素时,pyparsing示例失败:

[0]: [[['foo', 'bar'], ['baz', 'bar2']], [['foo', 'bob'], ['baz', 'fez']]]
[1]:
Traceback (most recent call last):
  File "json2.py", line 42, in <module>
    print "[1]:", results[1].dump()
  File "/Library/Python/2.7/site-packages/pyparsing.py", line 317, in __getitem__
    return self.__toklist[i]
IndexError: list index out of range

任何人都可以帮我识别这个语法有什么问题吗?

编辑:修复了尝试解析为JSON对象而非值的错误。

注意:这与:pyparsing: grammar for list of Dictionaries (erlang)有关,我基本上试图对Erlang数据结构做同样的事情,并以类似的方式失败:(

2 个答案:

答案 0 :(得分:3)

这可能是valid JSON,但你的语法不会处理它。这就是原因:

jsonObject << Dict( Suppress('{') + Optional(jsonMembers) + Suppress('}') )

这表示语法对象必须被{...}包围。你支持它作为一个数组[...]。由于顶级对象必须是字典,因此需要键名。将测试数据更改为:

{ "col1":{ "foo": "bar", "baz": "bar2" },
  "col2":{ "foo": "bob", "baz": "fez" } }

{ "data":[{ "foo": "bar", "baz": "bar2" },
          { "foo": "bob", "baz": "fez" }] }

将允许此语法解析它。想要一个顶级对象成为一个数组?只需修改语法!

答案 1 :(得分:2)

从此表达式返回的解析结果对象是匹配的标记的列表 - pyparsing不知道您是否要匹配一个或多个标记,因此它返回一个列表,在包含列表的情况下1个元素,dicts数组。

更改

results = jsonValue.parseString(testdata)

results = jsonValue.parseString(testdata)[0]

我认为情况会好转。完成后,我得到:

[0]: [['foo', 'bar'], ['baz', 'bar2']]
- baz: bar2
- foo: bar
[1]: [['foo', 'bob'], ['baz', 'fez']]
- baz: fez
- foo: bob