通过Python的eval()运行JSON?

时间:2009-07-05 00:35:11

标签: python json

除了最好的做法,是否有令人信服的理由来做到这一点?

我正在编写一个post-commit钩子,用于Google Code项目,该项目通过JSON对象提供提交数据。 GC提供HMAC身份验证令牌以及请求(在JSON数据之外),因此通过验证该令牌,我可以高度确信JSON数据是良性的(因为不信任Google)并且有效。

我自己(简短)的调查表明,JSON恰好是完全有效的Python,但"\/"转义序列除外 - GC似乎没有生成。

因此,当我使用Python 2.4(即没有json模块)时,eval()正在寻找真的诱人。

编辑:为了记录,我非常询问这是不是一个好主意。我相当意识到它不是,而且我非常怀疑即使我最终将它用于此项目,我也会将此技术用于任何未来的项目。我只是想确保我知道如果我这样做会遇到什么样的麻烦。 : - )

4 个答案:

答案 0 :(得分:28)

如果您对脚本工作正常一段时间感到满意,然后在一些模糊的边缘情况下随机失败,我会选择eval。

如果你的代码很健壮很重要,我会花时间添加simplejson。你不需要C部分来加速,所以将一些.py文件转储到某个目录中真的不难。

作为可能咬你的东西的一个例子,JSON使用Unicode而simplejson返回Unicode,而eval返回str:

>>> simplejson.loads('{"a":1, "b":2}')
{u'a': 1, u'b': 2}
>>> eval('{"a":1, "b":2}')
{'a': 1, 'b': 2}

编辑:eval()行为方式不同的更好示例:

>>> simplejson.loads('{"X": "\uabcd"}')
{u'X': u'\uabcd'}
>>> eval('{"X": "\uabcd"}')
{'X': '\\uabcd'}
>>> simplejson.loads('{"X": "\uabcd"}') == eval('{"X": "\uabcd"}')
False

编辑2:今天看到了SilentGhost指出的另一个问题:eval无法处理true - >是的,假的 - > False,null - >没有正确。

>>> simplejson.loads('[false, true, null]')
[False, True, None]
>>> eval('[false, true, null]')
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'false' is not defined
>>> 

答案 1 :(得分:11)

最佳实践的观点是,在大多数情况下,忽视它们是一个坏主意。如果我是你,我会使用解析器将JSON解析为Python。尝试simplejson,在我上次尝试时解析JSON非常简单,它声称与Python 2.4兼容。

我不同意不信任谷歌这一点。我不会不信任他们,但我会核实你从他们那里得到的数据。我实际使用JSON解析器的原因正好在你的问题中:

  

我自己(简短)的调查表明,JSON恰好是完全有效的Python,但“/”转义序列除外 - GC似乎没有生成。

是什么让您认为Google Code永远不会生成这样的转义序列?

如果您使用正确的工具,解析是一个已解决的问题。如果你试图采用这样的快捷方式,你最终会被错误的假设所困扰,或者你会做一些事情,比如当你的选择语言已经存在解析器时,尝试用正则表达式和布尔逻辑来破解解析器。

答案 2 :(得分:2)

一个主要区别是JSON中的布尔值为true | false,但Python使用True | False

不执行此操作的最重要原因可以概括为:eval永远不应该用于解释外部输入,因为这允许任意代码执行。

答案 3 :(得分:0)

eval JSON有点像尝试通过C ++编译器运行XML。

eval旨在评估Python代码。虽然存在一些语法上的相似之处,但 JSON不是Python代码。哎呀,它不仅不是 Python 代码,它不是代码开头。因此,即使你可以为你的用例侥幸逃脱,我也认为从概念上来说这是一个坏主意。 Python是一个苹果,JSON是橙味的苏打水。