Сериализация RegExp - программирование
Подтвердить что ты не робот

Сериализация RegExp

Итак, мне было интересно найти, что JSON.stringify сводит RegExp к пустому объектно-литералу (fiddle):

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

Ожидается ли такое поведение? Я понимаю, что RegExp - это объект без свойств для сериализации. Тем не менее, даты также являются объектами; но JSON.stringify() удается создать значимую строку:

JSON.stringify(new Date) // "2014-07-03T13:42:47.905Z"

Я бы надеялся, что JSON предоставит RegExp одинаковое рассмотрение, используя RegExp.prototype. toString().

4b9b3361

Ответ 1

Да, потому что в JSON нет канонического представления для объекта RegExp. Таким образом, это просто пустой объект.

редактировать - ну это 2018 сейчас; ответы, предлагающие решения с использованием .toJSON() т.д., вероятно, хороши, хотя я бы добавил метод к прототипу с

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

и так далее. Это гарантирует, что имя функции не будет перечисляемым, что делает обезьянку-патч более гигиеничной.

Ответ 2

Если кому-то будет интересно, есть хорошее обходное решение. Я не думаю, что текущее поведение верное. Например, экземпляр Date не сериализуется для пустого объекта, такого как RegExp, хотя это object, а также не имеет представления JSON.

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

Ответ 3

Оба JSON.stringify и JSON.parse могут быть настроены для выполнения пользовательской сериализации и десериализации с помощью аргументы replacer и reviver.

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

Ответ 4

Вот как я решил эту проблему:

Сериализуйте это как строку:

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

Затем перегидратируйте его, используя другое регулярное выражение:

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

Сохраняет шаблон и флаги - надеюсь, это кому-нибудь поможет!

Ответ 5

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)

Ответ 6

Я думаю, что хороший подход будет примерно таким:

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