Допустимо ли определять функции в результатах JSON? - PullRequest
97 голосов
/ 04 января 2010

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

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

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

Ответы [ 11 ]

98 голосов
/ 04 января 2010

номер

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

За http://en.wikipedia.org/wiki/JSON, поддерживаются «основные типы»:

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

Проблема в том, что 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.

7 голосов
/ 05 января 2015

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

Спецификация формата обмена данными в нотации объектов JavaScript (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".

7 голосов
/ 04 января 2010

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

4 голосов
/ 04 января 2010

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

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

3 голосов
/ 04 января 2010

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

2 голосов
/ 25 апреля 2018

Короткий ответ: NO ...

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

Обратите внимание на причину, по которой:

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

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

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

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

Но wait ...

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

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

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

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

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

eval(data.func)(); //return "a FUNC"
0 голосов
/ 11 мая 2019

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

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

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

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}
0 голосов
/ 30 января 2019

хотя 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>
0 голосов
/ 14 марта 2017

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

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