Учитывая такой блок:
var foo = {"regexp":/^http:\/\//,
"fun":function(){},
}
Как правильно хранить его в JSON?
Учитывая такой блок:
var foo = {"regexp":/^http:\/\//,
"fun":function(){},
}
Как правильно хранить его в JSON?
Вы должны сохранить 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, но ее основная цель по-прежнему заключается в инкапсуляции последовательности команд, а не в качестве обертки для базовых данных.
Вы не можете. JSON предназначен только для данных, а не для кода. Нет способа передать функции.
Вы можете сделать что-то вроде этого...
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
Почти хорошее решение, но не работает с регулярным выражением (для меня все равно)
// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
В ядре JSON нет; спецификация JSON разрешает только примитивные значения (string/numbers/boolean/null), а также массивы и объекты.
Для тех, кто все еще ищет ответ:
с плагином JSONfn вы можете сериализовать javascript-объект с помощью
и заново создайте объект из этой строки.
Документация: http://www.eslinstructor.net/jsonfn/
- Вадим
Это не JSON, но это форма сериализации: foo.toSource()
дает строковое представление: "({regexp:/^http:\\/\\//, fun:(function () {})})"
. Использование bar = eval(foo.toSource());
назначает новый объект с регулярным выражением и функцией bar
.
Я не знаю, насколько хорошо он поддерживается. На нескольких сайтах упоминается, что это только гекконы, хотя им уже два года. В настоящее время у меня есть только доступ к Firefox, поэтому вы проверяете, работает ли он в браузерах, которые вы хотите поддерживать (возможно, в IE, Chrome, Safari и Opera).
Я использовал и рекомендовал 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)
Это можно проверить, просмотрев их модульные тесты.
Все ответы выше правильные, вместо того, чтобы сохранить эту часть кода в виде строки, а затем выполните eval()
var sCode = 'var oFoo = {"regexp": new RegExp("/^http:\/\//"), "fun": function() {}}';
eval(sCode);
console.log(oFoo);