我可以在JSON中存储RegExp和Function吗?

Hua*_*ang 22 javascript regex serialization json anonymous-function

鉴于这样的块:

var foo = {"regexp":/^http:\/\//,
           "fun":function(){},
}
Run Code Online (Sandbox Code Playgroud)

将它存储在JSON中的正确方法是什么?

Ank*_*wal 33

您必须将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';
}
Run Code Online (Sandbox Code Playgroud)

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


Eve*_*ert 11

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


Bil*_*oon 7

你可以这样做......

方法

JSONEX = {

    stringify: function(obj){
        var jsonified = {}
        // loop through object and write string and type to newly stored data structure
        for(i in obj)
            jsonified[i] = {
                // some voodoo to determine the variable type
                type: Object.prototype.toString.call(obj[i]).split(/\W/)[2],
                value: obj[i].toString()
            }    
        return JSON.stringify(jsonified)
    },

    parse: function(json){
        objectified = {}
        obj = JSON.parse(json)
        // loop through object, and handle parsing of string according to type
        for(i in obj)
            if(obj[i].type == "RegExp"){
                var m = obj[i].value.match(/\/(.*)\/([a-z]+)?/)
                objectified[i] = new RegExp(m[1],m[2]);
            } else if(obj[i].type == "String"){
                objectified[i] = obj[i].value
            } else if(obj[i].type == "Function"){
                // WARNING: this is more or less like using eval
                // All the usual caveats apply - including jailtime
                objectified[i] = new Function("return ("+obj[i].value+")")();
            }
            // ADD MORE TYPE HANDLERS HERE ...

        return objectified

    }
}
Run Code Online (Sandbox Code Playgroud)

用法

myThing = {
    regex: new RegExp("123","g"),
    text: "good",
    func: function(x){
        return x * x
    }
}

json = JSONEX.stringify(myThing)
// "{"regex":{"type":"RegExp","value":"/123/g"},"text":{"type":"String","value":"good"},"func":{"type":"Function","value":"function (x) {\n    return x * x;\n}"}}"

obj = JSONEX.parse(json)
// native object representing original object
Run Code Online (Sandbox Code Playgroud)

NB

几乎是一个很好的解决方案,但不适用于正则表达式(无论如何)

http://jsonplus.com/

// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
Run Code Online (Sandbox Code Playgroud)

  • 包括“入狱”..那很好。哈哈!! (2认同)

Dmi*_*sky 6

长话短说:

对我来说,将两者存储为对象似乎是最好的:

{
    "regexp": {
        "body": "^http:\\/\\/",
        "flags": ""
    },
    "fun": {
        "args": [],
        "body": ""
    }
}
Run Code Online (Sandbox Code Playgroud)

正则表达式:

对于存储正则表达式已经有很多很好的答案:将它们存储为原始字符串,以便可以使用RegExp构造函数从字符串创建实际的正则表达式。

我的补充是要记住标志。OP 可能不需要它,但它肯定必须得到解决。RegExp构造函数将字符串形式的标志作为其第二个参数。因此 JSON 存储的正则表达式的约定是:

interface JSONStoredRegExp {
    body: string; // "" (empty string) for empty regexp
    flags: string; // "" (empty string) for zero flags
}
Run Code Online (Sandbox Code Playgroud)

...例如,这个 JSON:

{
    "regexp": {
        "body": "abc",
        "flags": "gi"
    }
}
Run Code Online (Sandbox Code Playgroud)

...会产生这个正则表达式:

{
    "regexp": {
        "body": "^http:\\/\\/",
        "flags": ""
    },
    "fun": {
        "args": [],
        "body": ""
    }
}
Run Code Online (Sandbox Code Playgroud)
interface JSONStoredRegExp {
    body: string; // "" (empty string) for empty regexp
    flags: string; // "" (empty string) for zero flags
}
Run Code Online (Sandbox Code Playgroud)

功能:

除非给定的函数是纯函数,否则通过 JSON 传输它对我来说似乎很奇怪。此外,这种算法的代码可能与除 JavaScript 之外的任何语言都不兼容。

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

interface JSONStoredFunction {
    args: string[]; // [] (empty array) for zero arguments
    body: string; // "" (empty string) for no-op function
}
Run Code Online (Sandbox Code Playgroud)

Function构造函数将 body 作为最后一个参数,并且每个参数都必须单独传递;所以这个 JSON:

{
    "fun": {
        "args": [ "x", "y" ],
        "body": "return x + y;"
    }
}
Run Code Online (Sandbox Code Playgroud)

...将产生这个函数:

{
    "regexp": {
        "body": "abc",
        "flags": "gi"
    }
}
Run Code Online (Sandbox Code Playgroud)
RegExp(json.regexp.body, json.regexp.flags);
Run Code Online (Sandbox Code Playgroud)

... 使用扩展运算符可能不方便。在这种情况下,使用.apply可能会有所帮助:

/abc/gi
Run Code Online (Sandbox Code Playgroud)


Jas*_*n S 2

在核心 JSON 中,没有;JSON 规范仅允许原始值(字符串/数字/布尔值/空)以及数组和对象。