14

我有这个 C# 对象:

var obj = new {
    username = "andrey",
    callback = "function(self) { return function() {self.doSomething()} (this) }"
}

我需要 JSON 序列化它以在 ajax 调用中传递给浏览器。我使用 JavascriptSerializer,但它序列化为以下 JSON:

{"username":"andrey", "callback": "function(self) { return function() {self.doSomething()} (this) }"}

但我需要的是:

{"username":"andrey", "callback": function(self) { return function() {self.doSomething()} (this) }}
  • 函数定义周围没有引号。

现在,当 JSON 对象到达浏览器并被创建时,'callback' 参数不是一个函数,而是一个字符串。知道如何解决它,最好是在服务器端?

4

3 回答 3

23

我试图完成类似的事情。在我的情况下,我使用 MVC Razor 语法尝试生成一个带有使用 @<text> 语法传入的函数的 json 对象。

我能够使用 Json.net 库(使用 JsonConvert 和 JRaw)获得所需的输出。

例子:

// set the property value using JRaw
var obj = new {
    username = "andrey",
    callback = new JRaw("function(self) { return function() {self.doSomething()} (this) }")
}
// and then serialize using the JsonConvert class
var jsonObj = JsonConvert.SerializeObject(obj);

那应该为您提供带有函数的 json 对象(而不是字符串中的函数)。

帖子: 如何将函数序列化为 json(使用 razor @<text>)

于 2013-05-28T20:04:27.130 回答
7

这种行为是故意的。JSON 不应该包含任何不是数据的东西——在你的例子中是一个可执行函数。如果数据可以从服务器以 JSON 格式返回,并且在执行时会运行任意功能(可以窃取信息、将用户重定向到恶意站点等),那么浏览器将面临巨大的安全风险。

JSON 的早期实现依赖于这样一个事实,即返回的数据可以通过 eval() 简单地执行以返回一个对象。然而,人们几乎立即意识到这会带来巨大的安全风险,并一直在努力应对。这就是为什么在标准化 JSON 对象之前,人们停止将原始 JSON 数据放入 eval() 并改用 JSON 解析库。

JSON 对象将始终仅将对象序列化为数据。这是设计使然。标准化的 JSON 格式无法表示可执行函数。

现在,您可以通过将浏览器上的回调传递给 eval() 轻松地将其转换为函数。但是,不要这样做。你只是敞开心扉接受黑客攻击。

在服务器端,现代浏览器旨在防止这种确切的事情发生——即从包含可执行功能的浏览器发送的数据。

于 2011-03-21T03:41:47.090 回答
0

您可以使用 Function 对象的构造函数。请参阅https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Function

在您的 json 中,您将回调属性设置为描述 Function 构造函数参数的字符串数组。然后,当 json 数据到达客户端时,您必须将 Array 转换为 Function 对象的实例。

这样您就可以在后台数据库中获得功能实现细节,而不是在源代码中硬编码。

const json = '{"username":"andrey","callback":["self","return self.doSomething()"]}';

//Parse the json to an object
const object = JSON.parse(json);

//Convert the callback property from Array to Function
object["callback"] = new Function(...object["callback"]);

//Create a parameter for calling the Function
var self = {
    doSomething() {
        console.log("Do something called");
    }
}

//Call the function
object["callback"](self);
于 2020-04-21T10:35:55.363 回答