Подтвердить что ты не робот

Могу ли я хранить RegExp и функцию в JSON?

Учитывая такой блок:

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

Как правильно хранить его в JSON?

4b9b3361

Ответ 1

Вы должны сохранить 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, но ее основная цель по-прежнему заключается в инкапсуляции последовательности команд, а не в качестве обертки для базовых данных.

Ответ 2

Вы не можете. JSON предназначен только для данных, а не для кода. Нет способа передать функции.

Ответ 3

Вы можете сделать что-то вроде этого...

Метод

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

    }
}

Использование

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.

Почти хорошее решение, но не работает с регулярным выражением (для меня все равно)

http://jsonplus.com/

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

Ответ 4

В ядре JSON нет; спецификация JSON разрешает только примитивные значения (string/numbers/boolean/null), а также массивы и объекты.

Ответ 5

Для тех, кто все еще ищет ответ:

с плагином JSONfn вы можете сериализовать javascript-объект с помощью

  • Функции
  • Regexp
  • Дата

и заново создайте объект из этой строки.

Документация: http://www.eslinstructor.net/jsonfn/

- Вадим

Ответ 6

Это не JSON, но это форма сериализации: foo.toSource() дает строковое представление: "({regexp:/^http:\\/\\//, fun:(function () {})})". Использование bar = eval(foo.toSource()); назначает новый объект с регулярным выражением и функцией bar.

Я не знаю, насколько хорошо он поддерживается. На нескольких сайтах упоминается, что это только гекконы, хотя им уже два года. В настоящее время у меня есть только доступ к Firefox, поэтому вы проверяете, работает ли он в браузерах, которые вы хотите поддерживать (возможно, в IE, Chrome, Safari и Opera).

Ответ 7

Я использовал и рекомендовал serialize-javascript пакет npm из yahoo. Он может сериализовать 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)

Это можно проверить, просмотрев их модульные тесты.

Ответ 8

Все ответы выше правильные, вместо того, чтобы сохранить эту часть кода в виде строки, а затем выполните eval()

var sCode = 'var oFoo = {"regexp": new RegExp("/^http:\/\//"), "fun": function() {}}';
eval(sCode);
console.log(oFoo);