2017-07-25 36 views
0

我在將通過腳本構建的字符串轉換爲JSON對象時遇到了一些麻煩(我試圖構建發佈數據以發出發佈請求API端點)。難以將字符串轉換爲JSON對象以便對其進行urlencode

,我發現了以下錯誤:

bos-mpqpu:config_parse rabdelaz$ python3 lexparse.py 
{"__class__":"HttpTestClient","description":"CP Codes","url":"://","serverip":"","method":"GET","enabled":true,"headers":[],"tests":[],"purge":false,"procs":[]} 
Traceback (most recent call last): 
    File "lexparse.py", line 448, in <module> 
print(ast.literal_eval(test_case_ACT_template.substitute({'protocol': "",'host': "", 'path' : "", 'query' : "", 'serverip' : "", 'tests' : ""}))) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 85, in literal_eval 
return _convert(node_or_string) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 66, in _convert 
    in zip(node.keys, node.values)) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 65, in <genexpr> 
    return dict((_convert(k), _convert(v)) for k, v 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 84, in _convert 
    raise ValueError('malformed node or string: ' + repr(node)) 
ValueError: malformed node or string: <_ast.Name object at 0x103c50c18> 

這裏是產生上述代碼:

test_case_ACT_template = Template('{"__class__":"HttpTestClient","description":"CP Codes","url":"$protocol://$host$path$query","serverip":"$serverip","method":"GET","enabled":true,"headers":[],"tests":[$tests],"purge":false,"procs":[]}') 


print(test_case_ACT_template.substitute({'protocol': "",'host': "", 'path' : "", 'query' : "", 'serverip' : "", 'tests' : ""})) 

print(ast.literal_eval(test_case_ACT_template.substitute({'protocol': "",'host': "", 'path' : "", 'query' : "", 'serverip' : "", 'tests' : ""}))) 

注意,第一個print語句導致輸出線與{"__class__"開始

我的總體目標是urlencode我的json字符串,但一些搜索SO導致我相信我應該先做在對它進行編碼之前,請使用210。

的最終目標是這樣的:

form_data = {'name' : 'CP Code Demo', 'configfilename' : '1-DR4E2_kona-ion.aws-eu-ssl.template_pm-2', 'type' : 'json', 'script' : urlencode(json.load(post_data))} 

post_data是一系列模板替換。

原來的錯誤,導致我開始尋找到ast.literal_eval如下:

Traceback (most recent call last): 
    File "lexparse.py", line 521, in <module> 
form_data = {'name' : 'CP Code Demo', 'configfilename' : '1-DR4E2_kona-ion.aws-eu-ssl.template_pm-2', 'type' : 'json', 'script' : urlencode(post_data)} 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 862, in urlencode 
"or mapping object").with_traceback(tb) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 854, in urlencode 
    raise TypeError 
TypeError: not a valid non-string sequence or mapping object 
+0

爲什麼在這個世界上你使用'ast.literal_eval()'這個?你究竟想在這裏實現什麼? – zwer

+0

稍微更新了我的問題。我的最終目標是對我在問題中顯示的模板中收集的數據進行urlencode編碼。 – Ramy

+0

你用什麼庫發送'form_data'?通常你不想做自己的轉義/編碼。 – zwer

回答

1

只要是符合的問題,您Template似乎產生了有效的JSON所以只是將其解析爲Python的dict,然後把它交給urllib.parse.urlencode()把它變成合法的URL參數,可以是這樣的:

import json 
from urllib.parse import urlencode 
from string import Template 

your_template = Template('{"__class__":"HttpTestClient","description":"CP Codes",' 
         '"url":"$protocol://$host$path$query","serverip":"$serverip",' 
         '"method":"GET","enabled":true,"headers":[],"tests":[$tests],' 
         '"purge":false,"procs":[]}') 

post_data = your_template.substitute({'protocol': "", 
             'host': "", 
             'path': "", 
             'query': "", 
             'serverip': "", 
             'tests': ""}) 

form_data = {'name': 'CP Code Demo', 
      'configfilename': '1-DR4E2_kona-ion.aws-eu-ssl.template_pm-2', 
      'type': 'json', 
      'script': urlencode(json.loads(post_data))} 

print(form_data) 

然後,你可以給它到任何你想要的。我仍然強烈建議解決您的證書問題,而不是將其與cURL抵消 - 嘗試通過CLI傳遞大量數據時可能遇到的問題可輕鬆解決您使用證書遇到的問題。

+0

這實際上很有幫助。我知道這是做這件事的一個糟糕的方式,但嬰兒的步驟。這只是爲了讓管理層參與項目。 – Ramy

+0

等待我在這裏看到另一個問題。 urlencode實際上將我的json對象變成了鍵值對。這其實不是我想要的。我想要的是逃避整個json對象並按原樣發佈。現在去谷歌,但如果你知道如何逃離,而不是編碼讓我知道。 – Ramy

+0

如果您想要URL轉義,請不要將其解析爲JSON - 只需將它提供給'urllib.parse.quote',例如''script':urllib.parse.quote(post_data)'。這一切都取決於你想要發送'script'值。從技術上講,你可以發送它沒有引用 - subprocess.Popen()應該轉義特殊字符,所以你可以將它傳遞給cURL,cURL應該能夠獨立處理其餘的。 – zwer

0

它失敗的原因是你沒有大寫True和False。

literal_eval將表達式評估爲Python對象,而不是JSON對象,但帶有約束條件。 Per the docs

ast.literal_eval(node_or_string) Safely evaluate an expression node or a Unicode or Latin-1 encoded string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

注意的地方說: 「布爾和無」。在Python中,布爾值是True和False,並且必須是大寫。你的字符串文字有'真'和'假'。

你可以把你的文字表達和直接看到它爲什麼不評價:

>>> x = {"__class__":"HttpTestClient","description":"CP Codes","url":"://","serverip":"","method":"GET","enabled":true,"headers":[],"tests":[],"purge":false,"procs":[]} 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'true' is not defined 

如果你試圖評估JSON數據,而不是使用AST模塊,你可以考慮JSON module