Допустимо ли определять функции в результатах JSON?

Часть ответа JSON веб-сайта содержала следующее (... добавлено для контекста):

{..., now:function(){return(new Date).getTime()}, ...}

Допустимо ли добавлять анонимные функции в JSON? Я ожидаю, что каждый раз, когда вы получаете доступ ко времени, вы возвращаете другое значение.

10 ответов

Решение

Нет.

JSON предназначен исключительно для описания данных. Как отмечается на http://www.json.org/, это "легкий формат обмена данными". - не язык программирования.

Согласно http://en.wikipedia.org/wiki/JSON, поддерживаются "основные типы":

  • Число (целое, действительное или с плавающей запятой)
  • String (Unicode с двойными кавычками с обратной косой чертой)
  • Логическое (истинное и ложное)
  • Массив (упорядоченная последовательность значений, разделенных запятыми и заключенная в квадратные скобки)
  • Объект (коллекция пар ключ-значение, разделенных запятыми и заключенных в фигурные скобки)
  • null

Проблема в том, что JSON как язык определения данных развился из JSON как нотация объектов JavaScript. Поскольку Javascript поддерживает eval в JSON, вполне закономерно помещать код JSON в JSON (в этом случае). Если вы используете JSON для удаленной передачи данных, то я бы сказал, что неправильно помещать методы в JSON, потому что вы, возможно, плохо смоделировали взаимодействие клиент-сервер. И далее, при желании использовать JSON в качестве языка описания данных, я бы сказал, что вы можете столкнуться с проблемами, внедрив методы, потому что некоторые анализаторы JSON были написаны с учетом только описания данных и могут не поддерживать определения методов в структуре.

Запись JSON в Википедии дает хороший повод не включать методы в JSON, ссылаясь на соображения безопасности:

Если вы абсолютно не доверяете источнику текста, и у вас нет необходимости анализировать и принимать текст, который не является строго JSON-совместимым, вам следует избегать eval() и использовать вместо него JSON.parse() или другой специфический JSON-анализатор. Анализатор JSON распознает только текст JSON и отклоняет другой текст, который может содержать вредоносный JavaScript. В браузерах, которые предоставляют встроенную поддержку JSON, анализаторы JSON также намного быстрее, чем eval. Ожидается, что нативная поддержка JSON будет включена в следующий стандарт ECMAScript.

Давайте процитируем одну из спецификаций - http://tools.ietf.org/html/rfc7159

Спецификация формата обмена данными в JavaScript Object Notation (JSON) гласит:

JSON является подмножеством JavaScript, но исключает присваивание и вызов.

Поскольку синтаксис JSON заимствован из JavaScript, можно использовать функцию eval() этого языка для анализа текстов JSON. Как правило, это представляет собой неприемлемую угрозу безопасности, так как текст
может содержать исполняемый код вместе с объявлениями данных. То же самое относится и к использованию eval()-подобных функций в любом другом языке программирования, в котором тексты JSON соответствуют этому.
синтаксис языка.

Поэтому все ответы, в которых говорится, что функции не являются частью стандарта JSON, являются правильными.

Официальный ответ: нет, нельзя определять функции в результатах JSON!


Ответ может быть да, потому что "код - это данные" и "данные - это код". Даже если JSON используется как независимый от языка формат сериализации данных, туннелирование "кода" через другие типы будет работать.

Строка JSON может использоваться для передачи функции JS браузеру на стороне клиента для выполнения.

[{"data":[["1","2"],["3","4"]],"aFunction":"function(){return \"foo bar\";}"}]

Это приводит к вопросу вроде: "Как выполнить код JavaScript, хранящийся в виде строки ".

Будьте готовы, чтобы поднять свой флаг "eval()- зло" и поставить рядом с ним свой флаг "не туннелировать через JSON".

Насколько я знаю, это не стандартно. Беглый взгляд на http://json.org/ подтверждает это.

Нет, определенно нет.

Если вы используете приличный сериализатор JSON, он не позволит вам сериализовать такую ​​функцию. Это действительный объект, но не действительный JSON. Каковы бы ни были намерения этого сайта, он не отправляет действительный JSON.

JSON явно исключает функции, потому что он не предназначен для структуры данных только для JavaScript (несмотря на JS в названии).

Короткий ответ НЕТ...

JSON - это текстовый формат, полностью независимый от языка, но использующий соглашения, знакомые программистам языков семейства C, включая C, C++, C#, Java, JavaScript, Perl, Python и многие другие. Эти свойства делают JSON идеальным языком обмена данными.

Посмотрите на причину, почему:

При обмене данными между браузером и сервером данные могут быть только текстовыми.

JSON - это текст, и мы можем преобразовать любой объект JavaScript в JSON и отправить JSON на сервер.

Мы также можем преобразовать любой JSON, полученный от сервера, в объекты JavaScript.

Таким образом, мы можем работать с данными как с объектами JavaScript, без сложного анализа и перевода.

Но подождите...

Есть еще способы сохранить вашу функцию, это широко не рекомендуется, но все же возможно:

Мы сказали, вы можете сохранить string... как насчет преобразования вашей функции в строку тогда?

const data = {func: '()=>"a FUNC"'};

Затем вы можете зашифровать данные, используя JSON.stringify(data) а затем с помощью JSON.parse разобрать его (если нужен этот шаг)...

И eval для выполнения строковой функции (перед этим просто сообщите, что использование eval широко не рекомендуется):

eval(data.func)(); //return "a FUNC"

С помощью NodeJS (синтаксис commonJS) я смог заставить этот тип функциональности работать, изначально у меня была просто структура JSON внутри некоторого внешнего файла JS, но я хотел, чтобы эта структура была больше классом, с методами, которые можно было бы решить на время выполнения.

Объявление Executor в myJSON не требуется.

var myJSON = {
    "Hello": "World",
    "Executor": ""
}

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}

Выражения функций в JSON полностью возможны, просто не забудьте заключить их в двойные кавычки. Вот пример из базы данных noSQL:

{
  "_id": "_design/testdb",
  "views": {
    "byName": {
      "map": "function(doc){if(doc.name){emit(doc.name,doc.code)}}"
    }
  }
}

Хотя eval не рекомендуется, это работает:

<!DOCTYPE html>
<html>
<body>

<h2>Convert a string written in JSON format, into a JavaScript function.</h2>

<p id="demo"></p>

<script>
    function test(val){return val + " it's OK;}
    var someVar = "yup";
    var myObj = { "func": "test(someVar);" };
    document.getElementById("demo").innerHTML = eval(myObj.func);
</script>

</body>
</html>

Оставьте цитаты...

var a = {"b":function(){alert('hello world');} };

a.b();
Другие вопросы по тегам