web-dev-qa-db-fra.com

Puis-je stocker RegExp et Function en JSON?

Étant donné un bloc comme celui-ci:

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

Quelle est la bonne façon de le stocker dans JSON?

20
Huang

Vous devez stocker RegExp en tant que chaîne dans l'objet JSON. Vous pouvez ensuite construire un objet RegExp à partir de la chaîne:

// 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';
}

En ce qui concerne les fonctions: elles ne doivent de toute façon pas être représentées en JSON ou XML. Une fonction peut être définie en tant qu'objet dans JS, mais son objectif principal est toujours d'encapsuler une séquence de commandes et de ne pas servir de wrapper pour les données de base.

30
Ankit Aggarwal

Tu ne peux pas. JSON est pour les données seulement, pas de code. Il n'y a aucun moyen de transférer des fonctions, sauf si vous pouvez d'abord le transformer en chaîne.

10
Evert

Vous pourriez faire quelque chose comme ça ...

Méthode

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

    }
}

Usage

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

N.B.

Presque une bonne solution, mais ne fonctionne pas avec regex (pour moi en tout cas)

http://jsonplus.com/

// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
7
Billy Moon

Pour ceux qui cherchent encore une réponse: 

avec plagin JSONfn vous pouvez sérialiser un objet javascript avec 

  • Fonctions
  • Regexp  
  • Date

et recréez un objet à partir de cette chaîne.

Documentation: http://www.eslinstructor.net/jsonfn/

--Vadim

2
vadimk

En JSON de base, il n'y en a pas; la spécification JSON autorise uniquement les valeurs primitives (chaîne/nombres/booléen/null), ainsi que les tableaux et les objets.

2
Jason S

J'ai utilisé et je recommanderais serialize-javascript npm à partir de yahoo. Il peut sérialiser JSON avec des fonctions et regex spécifiquement et gère d'autres cas.

De leurs docs:

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
});

produit

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

qui peut être hydraté avec

const obj = JSON.parse(serialized)

Ceci peut être vérifié en regardant leurs tests unitaires .

0
cchamberlain

Ce n'est pas JSON, mais c'est une forme de sérialisation: foo.toSource() donne une représentation sous forme de chaîne: "({regexp:/^http:\\/\\//, fun:(function () {})})". Utiliser bar = eval(foo.toSource()); assigne un nouvel objet avec une expression rationnelle et une fonction à bar.

Je ne sais pas si cela est bien pris en charge. Plusieurs sites Web mentionnent qu'il s'agit uniquement de gecko, bien qu'ils aient deux ans. Je n'ai actuellement accès qu'à Firefox, vous devez donc vérifier s'il fonctionne dans les navigateurs que vous souhaitez prendre en charge (probablement IE, Chrome, Safari et Opera).

0
Daan Wilmer