Javascript 我可以用JSON存储RegExp和函数吗?

Javascript 我可以用JSON存储RegExp和函数吗?,javascript,regex,json,serialization,anonymous-function,Javascript,Regex,Json,Serialization,Anonymous Function,给定这样一个块: var foo = {"regexp":/^http:\/\//, "fun":function(){}, } 用JSON存储它的正确方法是什么?你不能。JSON仅用于数据,不用于代码。除非可以先将函数转换为字符串,否则无法传输函数。在核心JSON中,没有;只允许原语值字符串/数字/布尔值/空值,以及数组和对象。以上所有答案都正确,您可以将这部分代码另存为字符串,然后进行求值 它不是JSON,但它是序列化的一种形式:foo.toSource给出了一个字符

给定这样一个块:

var foo = {"regexp":/^http:\/\//,
           "fun":function(){},
}

用JSON存储它的正确方法是什么?

你不能。JSON仅用于数据,不用于代码。除非可以先将函数转换为字符串,否则无法传输函数。

在核心JSON中,没有;只允许原语值字符串/数字/布尔值/空值,以及数组和对象。

以上所有答案都正确,您可以将这部分代码另存为字符串,然后进行求值


它不是JSON,但它是序列化的一种形式:foo.toSource给出了一个字符串表示:{regexp://^http:\\/\\//,fun:function{}。使用bar=evalfoo.toSource;将带有正则表达式和函数的新对象指定给bar


我不知道它得到了多大的支持。有几个网站提到它只是壁虎,尽管它们已经两岁了。我目前只能访问Firefox,因此您可以测试它是否在您想要支持的浏览器(可能是IE、Chrome、Safari和Opera)中工作。

您必须将RegExp作为字符串存储在JSON对象中。然后可以从字符串构造一个RegExp对象:

// JSON Object (can be an imported file, of course)
// Store RegExp pattern as a string
// Double backslashes are required to put literal \ characters in the string
var jsonObject = { "regex": "^http:\\/\\/" };

function fun(url) {
    var regexp = new RegExp(jsonObject.regex, 'i');

    var match;

    // You can do either:
    match = url.match(regexp);
    // Or (useful for capturing groups when doing global search):
    match = regexp.exec(url);

    // Logic to process match results
    // ...
    return 'ooga booga boo';
}

至于函数:无论如何,它们不应该用JSON或XML表示。在JS中,函数可以定义为对象,但它的主要用途仍然是封装一系列命令,而不是用作基本数据的包装器。

您可以这样做

方法 用法 请注意 这几乎是一个很好的解决方案,但对我来说,它不能与正则表达式一起工作


我已经使用并推荐雅虎的npm软件包。它可以专门用函数和正则表达式序列化JSON,并处理其他情况

从他们的文档中:

var serialize = require('serialize-javascript');

const serialized = serialize({
    str  : 'string',
    num  : 0,
    obj  : {foo: 'foo'},
    arr  : [1, 2, 3],
    bool : true,
    nil  : null,
    undef: undefined,

    fn: function echo(arg) { return arg; },
    re: /([^\s]+)/g
});
产生

'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"fn":function echo(arg) { return arg; },"re":/([^\\s]+)/g}'
它可以用水来补充水分

const obj = JSON.parse(serialized)
这可以通过查看它们的TL来验证。

TL;博士: 对我来说,将两者都存储为对象似乎是最好的:

{
    "regexp": {
        "body": "^http:\\/\\/",
        "flags": ""
    },
    "fun": {
        "args": [],
        "body": ""
    }
}
正则表达式: 存储regexp已经有很多很好的答案:将它们存储为原始字符串,这样就可以使用构造函数从字符串创建实际的regexp

我的补充是要记住国旗。OP可能不需要它,但它肯定需要解决。构造函数将字符串形式的标志作为其第二个参数。因此,JSON存储的regexp的契约是:

interface JSONStoredRegExp {
    body: string; // "" (empty string) for empty regexp
    flags: string; // "" (empty string) for zero flags
}
。。。例如,这个JSON:

{
    "regexp": {
        "body": "abc",
        "flags": "gi"
    }
}
{
    "fun": {
        "args": [ "x", "y" ],
        "body": "return x + y;"
    }
}
。。。将生成此regexp:

RegExpjson.regexp.body,json.regexp.flags; /abc/gi 功能: 除非给定的函数是纯函数,否则通过JSON传输它对我来说似乎很奇怪。此外,这种算法的代码可能与JavaScript以外的任何语言都不兼容

无论如何,如果仍然需要这样做,我建议使用相同的方法:将函数作为对象而不是字符串进行传递。还可以使用构造函数从参数和主体的序列化列表创建函数

interface JSONStoredFunction {
    args: string[]; // [] (empty array) for zero arguments
    body: string; // "" (empty string) for no-op function
}
构造函数将body作为其最后一个参数,每个参数都必须单独传递;所以这个JSON:

{
    "regexp": {
        "body": "abc",
        "flags": "gi"
    }
}
{
    "fun": {
        "args": [ "x", "y" ],
        "body": "return x + y;"
    }
}
。。。将产生此功能:

函数…json.fun.args,json.fun.body; 匿名函数x,y{返回x+y;} 使用……可能不方便。在这种情况下,使用.apply可能会有帮助:

Function.applynull,json.fun.args.concatjson.fun.body;
有很好的动作可以使用 一些新的JSON超集,包含许多JSON中非法的东西

{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}


github:

除非您通过regexp或解析器或其他方式明确地将字符串与安全模式匹配,否则不要使用eval,这是非常重要的——这就是JSON如此简单的原因之一;它可以被安全地解析。regexp可能是可消毒的,但不容易消毒;函数几乎肯定不是,并且可以通过哥德尔定理或类似技术证明。一般不要使用eval见我在Daan中的评论answer@JasonS我知道这一点,而这只是一种方式,黄想这样做。这个答案并没有对这样做的安全影响提出任何警告。如果您在答案本身中而不是在注释中添加了警告,那么这将是一个正确但危险的回答。嘿,这真的很酷,但是如果值是对象,JSONEX.stringify会给出{type:Object,value:[Object Object]}。var a={b:{c:'helloworld'}}有一条注释//在这里添加更多类型处理程序。。。这就是对象处理程序应该去的地方。这是一个关于如何制作解决方案的解释,而不是一个库,尽管如果是这样的话那就太好了![对象]-Internet Explorer再次攻击?包括监禁时间。。那很好。英雄联盟因此必须将RegExp标志例如:g、m和i存储在JSON中的单独字符串中?
{
    "fun": {
        "args": [ "x", "y" ],
        "body": "return x + y;"
    }
}
{
  // comments
  unquoted: 'and you can quote me on that',
  singleQuotes: 'I can use "double quotes" here',
  lineBreaks: "Look, Mom! \
No \\n's!",
  hexadecimal: 0xdecaf,
  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
  positiveSign: +1,
  trailingComma: 'in objects', andIn: ['arrays',],
  "backwardsCompatible": "with JSON",
}