【问题标题】:pyparsing: example JSON parser fails for list of dictspyparsing:示例 JSON 解析器对 dicts 列表失败
【发布时间】:2014-03-31 15:12:07
【问题描述】:

全部,

我正在尝试了解如何使用 pyparsing 处理字典列表。我已经回到example JSON parser 以获得最佳实践,但我发现它也无法处理字典列表!

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

#!/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 数据结构做同样的事情,但以类似的方式失败:(

【问题讨论】:

    标签: python json parsing pyparsing


    【解决方案1】:

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

    改变

    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
    

    【讨论】:

      【解决方案2】:

      这可能是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" }] }
      

      将允许此语法对其进行解析。想要一个顶级对象是一个数组吗?只需修改语法!

      【讨论】:

      • 感谢您发现我尝试解析为对象而不是一般值的错误,但这仍然无法以原始形式解析(我无法真正更改 JSON 的结构。我想修改语法来处理字典列表,但我不知道它有什么问题!
      • @DaveRigby 我现在无法测试它,但它看起来像jsonObject &lt;&lt; Dict( ((Suppress('{') + Optional(jsonMembers) + Suppress('}')) | jsonArray )
      • 是的,所以我更新了上面的测试代码以尝试解析为 jsonValue - 这确实解析无异常,但没有给我正确的字典列表 - 见上文。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 2022-08-19
      • 1970-01-01
      • 2016-05-31
      相关资源
      最近更新 更多