在JSON结果中定义函数是否有效?


98

网站的JSON响应的一部分具有以下内容(...为上下文添加):

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

向JSON添加匿名函数有效吗?我希望每次您访问“时间”时都返回不同的值。


JSON是否已通过浏览器成功解析?如果是这样,那么它是有效的(在这方面)。
harschware,2010年

7
@harschware-仅当JSON与javascript有关时才是正确的。作为一种独立于语言的数据序列化格式,它是错误的,是走下坡路的难题。
jsoverson

@jsoverson-我同意。请参阅下面的答案。
harschware,2010年

1
您自己可以轻松回答此问题:打开Web Kit检查器并运行:JSON.parse('{now:function(){return(new Date).getTime()}')。检查员说:Uncaught SyntaxError: Unexpected token n快速浏览JSON规范即可确认这一点。关注“价值”部分。
Mark E. Haase 2015年

Answers:


103

没有。

JSON纯粹是一种数据描述语言。如http://www.json.org所述,它是“轻量级数据交换格式”。-不是编程语言。

根据http://en.wikipedia.org/wiki/JSON,支持的“基本类型”为:

  • 数字(整数,实数或浮点数)
  • 字符串(带反斜杠转义的双引号Unicode)
  • 布尔值(对与错)
  • 数组(值的有序序列,用逗号分隔并括在方括号中)
  • 对象(键:值对的集合,用逗号分隔并括在花括号中)
  • null

2
@博士 Zim,不,将事物比较为null我所做的是这a==null?1:a.toString()==""是什么意思,如果a = null则返回1 / true,如果为“”则表示空字符串,您也将获得1 / true ..如果为不是null或“”,则它将返回0 / false,您可以将其复制更多以与[]和{}一起使用,只需将其添加?1:a==[]?1:a.toString()=={}.toString();到我的上一代码段即可。因此,此功能可能会对您有所帮助。isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})我会使用?1:0代替,?true:false但会使用(true / false)
JamesM-SiteGen 2011年

10
同时,功能也是数据。
argyle,2012年

2
我在这里找到了一种使用JSON来获取“更多数据”的方法。最好通知客户端(从服务器)如​​何获取更多数据,而无需担心客户端接下来要调用哪个REST或类似的api。
Ravindranath Akila

3
@RavindranathAkila REST意味着在调用中公开了可能的下一个API调用。换句话说:您所做的REST请求告诉您将来可能要执行的请求(基于应用程序决策逻辑和数据)。Github API就是一个很好的例子,其中返回了数据元素-但其中一些会导致其他API请求资源。
詹斯·科赫

1
@Jens-AndréKoch谢谢!将会检查出来
Ravindranath Akila 2015年

16

问题在于,JSON作为一种数据定义语言,是从JSON作为JavaScript对象表示法演变而来的。由于Javascript支持JSON上的eval,因此将JSON代码放入JSON(在该用例中)是合法的。如果您使用JSON远程传递数据,那么我会说将方法放入JSON中是不好的做法,因为您可能没有很好地对客户端-服务器交互进行建模。而且,此外,当希望使用JSON作为数据描述语言时,我会说您可能会因嵌入方法而陷入困境,因为某些JSON解析器仅考虑数据描述而编写,并且可能不支持结构中的方法定义。

Wikipedia JSON条目很好地证明了不包括JSON中的方法,并提到了安全问题:

除非您完全信任文本的来源,并且需要解析和接受不严格符合JSON的文本,否则应避免使用eval(),而应使用JSON.parse()或其他JSON特定的解析器。JSON解析器将仅识别JSON文本,并拒绝其他文本,其中可能包含恶意的JavaScript。在提供本机JSON支持的浏览器中,JSON解析器也比eval快得多。预计本机JSON支持将包含在下一个ECMAScript标准中。


2
您可能会通俗地使用术语JSON,但是正式地,“ JSON”是ECMA标准,其中没有包含要编码的功能对象。当您说“ JSON”时,您应该明确指的是哪些功能,这就是拥有标准的全部意义所在。
Mark E. Haase 2015年

同意今天是真的。我没有消息来源,但是我相信JSON是在ECMA进入Javascript游戏之前以及在JSON是标准数据交换格式之前创造的一个术语。因此,我使用了术语“演变”
harschware

@harschware根据RFC 4627,JSON由ECMA制成。
珍娜·史隆

9

让我们引用规范之一-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传递函数”标志。



4

不,绝对不是。

如果您使用了不错的JSON序列化程序,则不会让您序列化这样的函数。这是有效的对象,但无效的JSON。无论该网站的意图是什么,它都不会发送有效的JSON。


2
我使用JSON-Lib并将其视为出色的序列化程序。从[使用页面](json-lib.sourceforge.net/usage.html),您可以看到它可以对函数进行序列化
harschware 2010年

有趣的...我以前从未见过。绝对不是要规范(json.org明确声明JSON是独立于语言的,而函数定义不是),但仍然很有趣。
jvenema 2010年

有趣的是,它应该独立于语言,但JSON代表JavaScript Object Notation hmm weird ..
Nate-Wilkins 2013年


3

一个简短的答案是 ...

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"

0

通过使用NodeJS(commonJS语法),我能够使用这种功能,最初我在一些外部JS文件中只有一个JSON结构,但是我希望该结构更多地是一个Class,其方法可以在运行。

不需要在myJSON中声明“ Executor”。

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

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

-3

JSON中的函数表达式是完全可能的,只是不要忘记将其用双引号引起来。这是取自noSQL数据库设计的示例:

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


问题是关于函数而不是字符串。JSON支持字符串值,但不支持函数。有关详细信息,请参阅Mike的答案
jannis's

@jannis有可能。如果您添加类似的自调用功能。这里的人显然只是不知道答案。
罗伊,

-4

尽管不建议使用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>

1
因在示例中不需要使用HTML而被否决,这是5年的编码风格,缺少引号,并且JSON文件不应包含函数,如果它们不能被序列化或存储在一个没有SQL数据库,
马亭雅伯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.