2017-07-25 231 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