现在我有来自http请求的json字符串,但键不是字符串格式。例如,
>>> data_string = """
{
server_id: 1,
server_status: 200,
client: "client2",
content: [ {id: 0, info: "info0"}, {id: 2, info: "info2"} ]
}
"""
我想通过JSON格式化它,以便轻松提取数据字符串的字段。我有一个在python中使用eval的解决方案,
eval(data_string, type('Dummy', (dict,), dict(__getitem__ = lambda s, n: n))())
它给了我正确的数据:
{'server_id': 1, 'server_status': 200, 'client': 'client2', 'content': [{'id': 0, 'info': 'info0'}, {'id': 2, 'info': 'info2'}]}
请帮助我理解代码的技巧。 THX。
PS:我试过json但是失败了。但是,yaml.load(data_string)可以工作。答案 0 :(得分:4)
这一行
eval(data_string, type('Dummy', (dict,), dict(__getitem__ = lambda s, n: n))())
是非常丑陋的方式,与
一样class Dummy(dict):
def __getitem__(self, key):
return key
globals_obj = Dummy()
eval(data_string, globals_obj)
然后将此globals_obj
传递到globals
的{{1}}参数。 eval
必须是将名称映射到值的映射对象。现在,当globals
遇到正在使用的变量时,它将查询此映射对象,就像eval
一样。 globals_obj['variable_name']
方法只是将给定的密钥作为值返回,因此__getitem__
- > globals_obj[42]
,42
- > globals_obj[None]
等等。
这一切都非常不安全 - 如果服务器想要是恶意的,那么api就会回复像None
这样的代码。
如果这是 JavaScript 但不是 JSON ,您可以在__import__('os').system('execute an evil command')
模式下使用demjson
模块。它肯定比使用strict=False
更好,并且可能比使用YAML YAML parsers might be insecure更好。 And these bugs might be easily remotely exploitable
eval