如何将数组编码为包含json的函数


How to encode array to json containing function?

当我想要生成一个包含javascript函数的json字符串时,我遇到了一个小问题
我使用的是json_encode()函数,它可以很好地将任何对象/数组编码为json字符串。但是,我想用javascript函数填充一个元素值
json_encode()将始终将我的函数编码为字符串。如何删除"(报价)?引用"使我的函数成为一个字符串。这是一个例子:

$var['status']     = "oke";
$var['fnFeedback'] = "function (a,b,c){ return a+c.FnSource; }";
echo json_encode($var);
//then the result
{[status:"oke"],[fnFeedback:"function (a,b,c){ return a+c.FnSource; }"]}
//value of fnFeedback of above json is a string

如何使fnFeedback的值成为一个函数?

首先,您的示例不是合法的JSON语法。假设它是这样的:

var input = '{"status":"oke","fnFeedback":"function (a,b,c){return a+c.FnSource;}"}';

处理此问题的一种方法是正常解析,然后使用evalfnFeedback属性的值转换为Function对象。然而,使用eval通常是最后的手段(更不用说,如果您不能完全控制eval-ed的值,那么风险极高),这里有一种更好的方法,在解析JSON数据时使用一个小技巧。

诀窍是JSON.parse接受第二个参数,该参数应该是一个接受键/值对并返回结果的函数。这将对解析的每个元素调用。以下是一个将您的序列化函数字符串转换为实际函数的方法:

var result = JSON.parse(input,
    function(key, value) {
        // if value looks like a function definition, make a function
        if (value 
                && typeof value === "string" 
                && value.substr(0,8) == "function")
        {
            var startBody = value.indexOf('{') + 1;
            var endBody = value.lastIndexOf('}');
            var startArgs = value.indexOf('(') + 1;
            var endArgs = value.indexOf(')');
            return new Function(value.substring(startArgs, endArgs),
                                value.substring(startBody, endBody));
        }
        // else just return the value as is
        return value;
    });

运行时,您可以看到结果:

>result["反馈"]
【功能】
>result['fFeedback'].toString()
'函数匿名(a,b,c){''n返回a+c.FnSource;''n}'

关于这部作品的更详细的解释可以在这里找到(以上内容改编自此)。另一个使用相同想法(我还没有测试过)的(可能更干净的)示例代码的JavaScript要点。

你不能。JSON的意思是:JavaScriptOobjectN旋转。它是一个对象所有属性的String值的串行化。函数属性不可序列化。如果将JSON字符串反序列化为Object,则必须将包含该函数的字符串转换为真正的javascript函数(例如,使用evalnew Function)。

另请参阅,第5章:

JSON值可以是对象、数组、数字、字符串、true、false或空

JSON不能直接表示函数体。

假设JSON被转换回JS对象(下面称为myObj),一种可能性是将字符串直接转换为函数,方法是将其封装在括号中(从而将函数声明转换为函数表达式),然后将其传递给eval:

var fnFeedback = eval('(' + myObj.fnFeedback + ')';

请注意,使用eval可能存在安全问题——使用时要格外小心,不要信任第三方间接提供的任何功能体。使用Function更安全,请参阅Ted Hopp稍后的回答。