在 JSON 中传递 javascript 函数

Passing javascript function in JSON

我正在尝试使用单击事件处理程序实现 jQCloud 词云。它要求我在 JSON.

中传递一个 javascript 函数

在 C# 中,我制作了动态 JSON 文本

foreach (var r in result)
{
    sbChart.Append("{\"text\": \"" + r.Key + "\", \"weight\": " + r.Count().ToString() + ", ");
    sbChart.Append("\"handlers\": { \"click\": \"function() { alert('You clicked " + r.Key + "');}\"}}, ");
}
if (sbChart.Length != 0)
{
    returnString = "[" + sbChart.ToString().Substring(0, sbChart.Length - 2) + "]";
}

我 return 通过 web 方法到 javascript 我的代码是

var words = JSON.parse(strJSON);
$('#div').jQCloud(words);

生成的JSON是

[
  {"text": "the", "weight": 111, "handlers": { "click": "function() { alert('You clicked the');}"}}, 
  {"text": "in", "weight": 66, "handlers": { "click": "function() { alert('You clicked in');}"}}
]

但是,由于我的函数是一个字符串,所以它不会作为对象执行。如果我删除函数语句前后的双引号,它会在解析期间给我 Invalid Character 错误。

任何人都可以帮助我如何使此警报起作用?

函数不应该作为 JSON 传递,执行数据调用传递的任意逻辑是一个相当大的安全问题。也就是说,使用 eval 来解决这个问题。

类似

var action = eval(response[0].handlers.click); // evaluates the string as javascript, and returns the value, in this case a function.

action();

如果您确实以这种方式将函数传递给您的页面(请参阅下面的"but"),您可以为它使用 eval,因为你是提供文本的人,你将 evaling 它没有安全问题(而且速度问题不是问题,并且一直多年)。我不确定你想用这个函数做什么,但是例如:

$(".foo").on("click", eval(words[0].handlers.click));

...将评估函数并将结果分配为与 .foo 选择器匹配的元素的点击处理程序。

但是,几乎可以肯定有更好的方法来构建事物。不是在 JSON 中传回函数,您可能在 JavaScript 中已经在某种映射中拥有这些函数:

var clickHandlers = {
    "the": function() { alert("You clicked the"); },
    "in": function() { alert("You clicked the"); }
};

...然后在您的 JSON.

中给出密钥 ("the", "in")

或者,假设除了被点击的内容之外它们是相同的东西,从被点击的元素中找出被点击的内容("the" 或 "in")。

或其他许多东西中的任何一个,但它们的共同点是函数是在您的 JavaScript 代码中定义的,而不是通过 JSON 发回的,然后您 link 通过 JSON 中的信息而不是 JSON.

中的实际 函数 来增加这些函数

非常感谢您提出以上建议。但我最终使用了 how to provide a click handler in JQCloud

的答案

我根据自己的要求对其进行了一些修改,并且成功了

var tag_list = new Array();
    var obj = GetCustomJsonObj(strJSON);
    for (var i = 0; i < obj.length; i++) {
        tag_list.push({
            text: obj[i].text,
            weight: obj[i].weight,
            //link: obj[i].link,
            handlers: {
                click: function () {
                    var zz = obj[i];
                    return function () {
                        alert("you have clicked " + zz.text);
                    }
                }()
            }
        });
    }