Запуск JSON через Python eval()?

Лучшие практики в стороне, есть ли веская причина не для этого?

Я пишу post-commit hook для использования с проектом Google Code, который предоставляет данные фиксации через объект JSON. GC предоставляет токен аутентификации HMAC вместе с запросом (за пределами данных JSON), поэтому, проверяя этот токен, я получаю высокую уверенность в том, что данные JSON являются как доброкачественными (так как мало оснований доверять Google) и действительны.

Мои собственные (краткие) исследования показывают, что JSON оказывается полностью допустимым Python, за исключением escape-последовательности "\/", который GC не появляется для генерации.

Итак, когда я работаю с модулем Python 2.4 (т.е. нет json), eval() выглядит действительно заманчивым.

Изменить:. Для записи я очень сильно не спрашиваю, является ли это хорошей идеей. Я вполне понимаю, что это не так, и я очень сомневаюсь, что когда-либо буду использовать этот метод для любых будущих проектов, даже если я в конечном итоге использую его для этого. Я просто хотел убедиться, что знаю, какие проблемы я натолкну: -)

Ответ 1

Если вам комфортно работать с вашей программой script на некоторое время, а затем случайным образом провалиться на каком-то неясном краевом случае, я бы пошел с 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 → True, false → False, null → None правильно.

>>> 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
>>> 

Ответ 2

Пункт передовой практики заключается в том, что в большинстве случаев это плохая идея игнорировать их. Если бы я был вами, я бы использовал парсер для анализа JSON на Python. Попробуйте simplejson, это было очень просто для синтаксического анализа JSON, когда я в последний раз его пробовал, и утверждает, что он совместим с Python 2.4.

Я не согласен с тем, что мало что стоит в недоверии Google. Я бы не стал им доверять, но я бы проверял данные, полученные от них. Причина, по которой я на самом деле использовал парсер JSON, прямо в вашем вопросе:

Мои собственные (краткие) исследования показывают, что JSON оказывается полностью действительным Python, за исключением "escape-последовательности" /, который GC, похоже, не генерирует.

Почему вы думаете, что Google Code никогда не будет генерировать escape-последовательность?

Разбор разрешен, если вы используете нужные инструменты. Если вы попытаетесь использовать такие ярлыки, вы, в конце концов, будете укушены неправильными предположениями, или вы сделаете что-то вроде попыток взломать парсер с регулярным выражением и логической логикой, когда парсер уже существует для вашего языка выбора.

Ответ 3

Одно существенное отличие состоит в том, что логическое значение в JSON равно true | false, но Python использует true | false.

Самая важная причина, почему этого не делать, может быть обобщена: eval никогда не должен использоваться для интерпретации внешнего ввода, поскольку это позволяет выполнять произвольный код.

Ответ 4

eval ing JSON немного похож на попытку запуска XML через компилятор С++.

eval предназначен для оценки кода Python. Хотя существуют синтаксические сходства, JSON не является кодом Python. Черт, не только это не код Python, это не код для начала. Поэтому, даже если вы можете уйти с этим для своего прецедента, я бы сказал, что это плохая идея концептуально. Python - яблоко, JSON - содовая апельсиновая сода.