Posso conservare le RegExp e Funzione in JSON?

Dato un blocco come questo:

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

Che cosa è un buon modo per memorizzare in JSON?

OriginaleL’autore Huang | 2011-11-30

8 risposte

  1. 29

    Si devono memorizzare le RegExp come una stringa in un oggetto JSON. Si può quindi costruire un oggetto RegExp dalla stringa:

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

    Come per le funzioni: non devono essere rappresentati in JSON o XML comunque. Una funzione può essere definita come un oggetto in JS, ma il suo scopo principale è ancora quello di incapsulare una sequenza di comandi, non servire come un wrapper per i dati di base.

    OriginaleL’autore Ankit Aggarwal

  2. 10

    Non si può. JSON è di solo i dati, non il codice. Non c’è modo per il trasferimento di funzioni.

    OriginaleL’autore Evert

  3. 7

    Si potrebbe fare qualcosa di simile a questo…

    Metodo

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

    Utilizzo

    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.

    Quasi una buona soluzione, ma non funziona con regex (per me comunque)

    http://jsonplus.com/

    //doing this: jsonPlus.stringify(myThing)
    //just stores `regex` as an empty object
    ehi, questo è davvero cool, ma JSONEX.stringify dà {"type":"Object","value":"[object Object]"} se il valore è un oggetto. Ex: var a = {b: {c: 'hello world'}}
    C’è un commento // ADD MORE TYPE HANDLERS HERE ... che è dove l’oggetto gestore deve andare. Questa è una spiegazione di come fare una soluzione, non una biblioteca, anche se sarebbe bello se fosse!
    [object Object] – Internet Explorer colpisce ancora?

    OriginaleL’autore Billy Moon

  4. 2

    In core JSON, non c’è; JSON spec consente solo per i valori di base (string/numeri/boolean/null), array e oggetti.

    OriginaleL’autore Jason S

  5. 2

    Per chi è ancora alla ricerca di una risposta:

    con plagin JSONfn è possibile serializzare un oggetto javascript con

    • Funzioni
    • Regexp
    • Data

    e ri-creare l’oggetto da questa stringa.

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

    –Vadim

    OriginaleL’autore vadimk

  6. 0

    Non è JSON, ma è una forma di serializzazione: foo.toSource() dà una rappresentazione in forma di stringa: "({regexp:/^http:\\/\\//, fun:(function () {})})". Utilizzando bar = eval(foo.toSource()); assegna un nuovo oggetto con una regex e una funzione di bar.

    Non so come livello di supporto. Il sito web più dire che è gecko-solo, anche se sono due anni. Io attualmente hanno accesso solo per Firefox, in modo da verificare se funziona nei browser che si desidera il supporto (probabilmente IE, Chrome, Safari e Opera).

    Non utilizzare eval meno che non abbiano espressamente abbinato una stringa con un “sicuro” pattern (sia per mezzo di espressioni o parser o qualsiasi altra cosa), che non è banale-che è una ragione per cui JSON è così semplice; può essere analizzato in modo sicuro. Regexp sono probabilmente sanitizable (ma non così facilmente); le funzioni sono quasi certamente probabilmente non e dimostrabile tramite il teorema di Godel o alcune di queste tecniche.

    OriginaleL’autore Daan Wilmer

  7. 0

    Ho usato e lo consiglio serializzare-javascript npm pacchetto da yahoo. È possibile che la serializzazione JSON con funzioni e le regex in particolare e gestisce altri casi.

    Da loro documenti:

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

    produce

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

    che possono essere idratata con

    const obj = JSON.parse(serialized)

    Questo può essere verificato osservando il loro unit test.

    OriginaleL’autore cchamberlain

  8. -1

    Tutte le risposte di cui sopra è di destra, invece, è possibile salvare questa parte di codice come una stringa e quindi fare eval()

    var sCode = 'var oFoo = {"regexp": new RegExp("/^http:\/\//"), "fun": function() {}}';
    eval(sCode);
    console.log(oFoo);
    Non utilizzare eval in generale (vedi il mio commento in Daan risposta)
    So che questo è solo un modo di fare che Huang vuole
    Questa risposta non dare alcun tipo di avvertimenti circa le implicazioni di sicurezza di questo metodo. se si aggiunge l’attenzione all’interno della risposta stessa, piuttosto che nel commento, quindi sarebbe corretto anche se pericoloso risposta.

    OriginaleL’autore balkon_smoke

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *