2016-03-06 119 views
1

我正在嘗試編寫解析器來處理來自注冊商API的響應數據。格式不是我以前見過的格式,所以這可能非常簡單;如果有人認識到這一點,請告訴我,可能有一個預先存在的庫來處理它。但是現在我正在假設我需要自己解析它。爲什麼pyparser的asDict()返回一個空dict而不是一個列表?

我的語法如下:

equals = Literal("=").suppress() 
lbracket = Literal("[").suppress() 
rbracket = Literal("]").suppress() 
lbrace = Literal("{").suppress() 
rbrace = Literal("}").suppress() 

value_dict   = Forward() 
value_list   = Forward() 
value_string  = Word(alphanums + "@. ") 

value    = value_list^value_dict^value_string 
values    = Group(delimitedList(value, ",")) 
value_list   << lbracket + values + rbracket 

identifier   = Word(alphanums + "_.") 

assignment   = Group(identifier + equals + Optional(value)) 
assignments   = Dict(delimitedList(assignment, ';')) 
value_dict   << lbrace + assignments + rbrace 

response = assignments 

當我運行這個簡單的測試案例:

rsp = 'username=goat; errors={username=[already taken, too short]}; empty_field=' 
result = response.parseString(rsp) 
print result.asDict() 

我得到如下:

{'username': 'goat', 'empty_field': '', 'errors': {'username': {}}} 

錯誤[ '用戶名']應該是一個字符串列表,但顯示爲空字典。當我使用.dump()的參數,可以看起來一切都很好:

ss = response.searchString(rsp) 
for i in ss: 
    print i.dump() 

產量:

- empty_field: 
- errors: [['username', ['already taken', 'too short']]] 
    - username: ['already taken', 'too short'] 
- username: goat 

我在做什麼錯在這裏?

回答

0

在當前版本的pyparsing中,這是一個天真的實現asDict()。在yoru語法中,您可以創建兩種不同樣式的ParseResults:帶名稱的結果和僅僅是普通列表的結果。 asList()只是遍歷一個嵌套的ParseResults獲取列表和子列表,所以asDict()的工作原理類似。然而,asDict()確實需要對可能存在的值的類型稍微聰明點 - 目前,這是pyparsing中的一個錯誤。

編輯

要解決這個問題,你需要做一些工作來列表存儲爲實際的列表,而不是ParseResults。重新定義values表達式:

values = delimitedList(value, ",").setParseAction(lambda toks: [toks.asList()]) 

因爲這將不返回解析列表作爲ParseResults,但作爲一個實際的名單,toDict()不會試圖把它變成一個字典。

+0

如果我能做些什麼來解決這個問題,你知道嗎?我真的不希望編寫一個遞歸迭代器來遍歷整個數據集,並「修復」那些沒有返回我期望的結果的東西。 –

+0

原來這個'toDict()'的遞歸版本並不那麼容易。我會再考慮一下,希望能儘快將更聰明的'toDict'版本簽入SVN。 – PaulMcG

+0

更新後的版本修復asDict()以正確識別字典與不加鍵列表,檢入SVN – PaulMcG

相關問題