Serialization of RegExp

前端 未结 6 1745
北荒
北荒 2020-12-16 10:01

So, I was interested to find that JSON.stringify reduces a RegExp to an empty object-literal (fiddle):

JSON.stringify(/^[0-9]+$/) // \"{}\"


        
相关标签:
6条回答
  • 2020-12-16 10:13

    I think a good approach would be something like this:

    function stringifyFilter(key,value) {
        if (value instanceof RegExp) {
            return value.toString();
        }
    
        return value;
    }
    
    var myObj = {
        text : 'Howdy ho!',
        pattern : /[a-z]+/i
    }
    
    JSON.stringify(myObj,stringifyFilter); // output: {"text":"Howdy ho!","pattern":"/[a-z]+/i"}
    
    0 讨论(0)
  • 2020-12-16 10:20

    Yes, because there's no canonical representation for a RegExp object in JSON. Thus, it's just an empty object.

    edit — well it's 2018 now; the answers suggesting solutions using .toJSON() etc are probably fine, though I'd add the method to the prototype with

    Object.defineProperty(RegExp.prototype, "toJSON", {
      value: RegExp.prototype.toString
    });
    

    and so on. That ensures that the function name isn't enumerable, which makes the monkey-patch somewhat more hygienic.

    0 讨论(0)
  • 2020-12-16 10:23

    If somebody would be interested, there is a nice workaround. I don't think, that current behaviour is correct. For example, Date instance is not serialized to empty object like RegExp, though it is an object and also has no JSON representation.

    RegExp.prototype.toJSON = RegExp.prototype.toString;
    
    
    // sample
    var foo = { rgx: /qux$/ig, date: new Date }
    
    JSON.stringify(foo);
    //> {"rgx":"/qux$/gi","date":"2014-03-21T23:11:33.749Z"}"
    
    0 讨论(0)
  • 2020-12-16 10:24

    Both JSON.stringify and JSON.parse can be customized to do custom serialization and deserialization by using the replacer and reviver arguments.

    var o = {
      foo: "bar",
      re: /foo/gi
    };
    
    function replacer(key, value) {
      if (value instanceof RegExp)
        return ("__REGEXP " + value.toString());
      else
        return value;
    }
    
    function reviver(key, value) {
      if (value.toString().indexOf("__REGEXP ") == 0) {
        var m = value.split("__REGEXP ")[1].match(/\/(.*)\/(.*)?/);
        return new RegExp(m[1], m[2] || "");
      } else
        return value;
    }
    
    console.log(JSON.parse(JSON.stringify(o, replacer, 2), reviver));

    You just have to come up with your own serialization format.

    0 讨论(0)
  • 2020-12-16 10:31

    Here's how I solved this issue:

    Serialize it as a string:

    var pattern = /foobar/i;
    var serialized = JSON.stringify(pattern.toString());
    

    Then rehydrate it using another regex:

    var fragments = serialized.match(/\/(.*?)\/([a-z]*)?$/i);
    var rehydrated = new RegExp(fragments[1], fragments[2] || '');
    

    Preserves the pattern and flags - hope this helps someone!

    0 讨论(0)
  • 2020-12-16 10:31
    RegExp.prototype.toJSON = RegExp.prototype.toString;
    
    var regexp = /^[0-9]+$/;
    var foo = { rgx: regexp.source, date: new Date };
    var stringified = JSON.stringify(foo);
    new RegExp(JSON.parse(stringified).rgx)
    
    0 讨论(0)
提交回复
热议问题