有没有可能让JSON.stringify保留函数?

cam*_*o2k 23 javascript json object

拿这个对象:

x = {
 "key1": "xxx",
 "key2": function(){return this.key1}
}
Run Code Online (Sandbox Code Playgroud)

如果我这样做:

y = JSON.parse( JSON.stringify(x) );
Run Code Online (Sandbox Code Playgroud)

然后你会回来{ "key1": "xxx" }.有没有什么可以通过stringify传递函数?使用"ye goode olde eval()"创建具有附加功能的对象,但包装它的是什么?

Art*_*org 9

我遇到了同样的问题,还有一个类似于你的帖子发现了json-stringify-function.以下内容可能对您有用:

var JSONfn;
if (!JSONfn) {
    JSONfn = {};
}

(function () {
  JSONfn.stringify = function(obj) {
    return JSON.stringify(obj,function(key, value){
            return (typeof value === 'function' ) ? value.toString() : value;
        });
  }

  JSONfn.parse = function(str) {
    return JSON.parse(str,function(key, value){
        if(typeof value != 'string') return value;
        return ( value.substring(0,8) == 'function') ? eval('('+value+')') : value;
    });
  }
}());
Run Code Online (Sandbox Code Playgroud)

代码片段取自Vadim Kiryukhin的JSONfn.js或参见主页上的文档


Mik*_*uel 6

您无法打包功能,因为它们关闭的数据对任何序列化程序都不可见.即使是Mozilla uneval也无法正确打包.

最好的选择是使用复活器和替换器.

https://yuilibrary.com/yui/docs/json/json-freeze-thaw.html

传递给JSON.parse的reviver函数应用于原始解析对象中从最深键到最高级别的所有键:值对.在我们的例子中,这意味着名称和已发现的属性将通过reviver传递,然后包含这些键的对象将被传递.


Tom*_*icz 5

从技术上讲,这不是JSON,我也很难想象你为什么要这样做,但尝试以下hack:

x.key2 = x.key2.toString();
JSON.stringify(x)  //"{"key1":"xxx","key2":"function (){return this.key1}"}"
Run Code Online (Sandbox Code Playgroud)

当然,第一行可以通过在对象上递归迭代来自动化.反向操作更难 - 函数只是一个字符串,eval可以工作,但你必须猜测给定的键是否包含字符串化的函数代码.


Mar*_*arz 5

这就是我所做的https://gist.github.com/Lepozepo/3275d686bc56e4fb5d11d27ef330a8ed

function stringifyWithFunctions(object) {
  return JSON.stringify(object, (key, val) => {
    if (typeof val === 'function') {
      return `(${val})`; // make it a string, surround it by parenthesis to ensure we can revive it as an anonymous function
    }
    return val;
  });
};

function parseWithFunctions(obj) {
  return JSON.parse(obj, (k, v) => {
    if (typeof v === 'string' && v.indexOf('function') >= 0) {
      return eval(v);
    }
    return v;
  });
};
Run Code Online (Sandbox Code Playgroud)


Chr*_*ian 5

最近我也有类似的要求。需要明确的是,输出看起来像JSON,但实际上只是javascript。

JSON.stringify 在大多数情况下都可以正常工作,但是功能会“失败”。

我得到了一些技巧:

  1. 利用replacer(的第二个参数JSON.stringify()
  2. 用于func.toString()获取函数的JS代码
  3. 记住哪些函数已被字符串化,并直接将其替换为结果

这是它的样子:

// our source data
const source = {
    "aaa": 123,
    "bbb": function (c) {
        // do something
        return c + 1;
    }
};

// keep a list of serialized functions
const functions = [];

// json replacer - returns a placeholder for functions
const jsonReplacer = function (key, val) {
    if (typeof val === 'function') {
  	    functions.push(val.toString());
        
        return "{func_" + (functions.length - 1) + "}";
    }
        
    return val;
};

// regex replacer - replaces placeholders with functions
const funcReplacer = function (match, id) {
   return functions[id];
};

const result = JSON
    .stringify(source, jsonReplacer)               // generate json with placeholders
    .replace(/"\{func_(\d+)\}"/g, funcReplacer);   // replace placeholders with functions

// show the result
document.body.innerText = result;
Run Code Online (Sandbox Code Playgroud)
body { white-space: pre-wrap; font-family: monospace; }
Run Code Online (Sandbox Code Playgroud)

重要提示:请注意占位符格式-确保它不太通用。如果您更改它,还请更改相应的正则表达式。