我可以在JSON存储RegExp和函数
Can I store RegExp and Function in 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中可以定义为对象,但其主要目的仍然是封装命令序列,而不是作为基本数据的包装器。
你可以这样做…
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
注意:
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
几乎是一个很好的解决方案,但不与regex工作(对我来说)
http://jsonplus.com/// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
br:
将两者都存储为对象对我来说似乎是最好的:
{
"regexp": {
"body": "^http:''/''/",
"flags": ""
},
"fun": {
"args": [],
"body": ""
}
}
regexp:
关于存储regexp已经有很多很好的答案:将它们存储为原始字符串,以便可以使用RegExp
构造器从字符串创建实际的regexp。
我的补充是要记住标记。OP可能不需要它,但它肯定必须解决。RegExp
构造函数接受字符串形式的标志作为其第二个参数。所以json存储的regexp的契约是:
interface JSONStoredRegExp {
body: string; // "" (empty string) for empty regexp
flags: string; // "" (empty string) for zero flags
}
…例如,这个JSON:
{
"regexp": {
"body": "abc",
"flags": "gi"
}
}
…将产生以下regexp:
RegExp(json.regexp.body, json.regexp.flags);
/abc/gi
功能:
除非给定的函数是纯的,否则通过JSON传输它对我来说似乎很奇怪。此外,这种算法的代码可能与除了JavaScript之外的任何语言都不兼容。
无论如何,如果仍然需要这样做,我将推荐相同的方法:将函数作为对象,而不是字符串。还可以使用Function
构造函数从序列化的参数列表和函数体创建函数。
interface JSONStoredFunction {
args: string[]; // [] (empty array) for zero arguments
body: string; // "" (empty string) for no-op function
}
Function
构造函数以body作为最后一个参数,每个参数必须单独传递;所以这个JSON:
{
"fun": {
"args": [ "x", "y" ],
"body": "return x + y;"
}
}
…将产生如下函数:
Function(...json.fun.args, json.fun.body);
function anonymous(x, y) { return x + y; }
使用...
作为展开运算符可能不方便。在这种情况下,使用.apply
可能会有所帮助:
Function.apply(null, json.fun.args.concat(json.fun.body));
在core JSON中,没有;JSON规范只允许原始值(string/numbers/boolean/null)、数组和对象。
有很好的运动使用https://json5.org/一些新的JSON超集,包含了很多JSON中不合法的东西
{
// comments
unquoted: 'and you can quote me on that',
singleQuotes: 'I can use "double quotes" here',
lineBreaks: "Look, Mom! '
No ''n's!",
hexadecimal: 0xdecaf,
leadingDecimalPoint: .8675309, andTrailing: 8675309.,
positiveSign: +1,
trailingComma: 'in objects', andIn: ['arrays',],
"backwardsCompatible": "with JSON",
}
github: https://github.com/json5/json5
它不是JSON,但它是一种序列化形式:foo.toSource()
给出字符串表示:"({regexp:/^http:''/''//, fun:(function () {})})"
。使用bar = eval(foo.toSource());
将一个带有正则表达式和函数的新对象赋给bar
。
我不知道它有多受支持。几个网站提到,这是壁虎的专属,尽管他们已经两岁了。我目前只能访问Firefox,所以你可以测试它是否可以在你想要支持的浏览器(可能是IE, Chrome, Safari和Opera)中工作。
我已经使用并推荐雅虎的serialize-javascript npm包。它可以用函数和正则表达式序列化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)
这可以通过查看他们的单元测试来验证。
在JSON中保存正则表达式模式是一件痛苦的事情。一个正则表达式字符串,如/^'S+@'S+'.'S+$/
(用于检查电子邮件地址格式)需要在JSON中转义到/^''S+@''S+''.''S+$/
才能成为有效的JSON。
在javascript中,为了避免必须处理我存储在JSON中的转义和反转义正则表达式模式,我在解析JSON之前使用encodeURIComponent()
对正则表达式模式进行编码。因此,如果我想保存一个正则表达式模式,如{"pattern": "/^'S+@'S+'.'S+$/"}
在JSON(这将不会验证为JSON),那么编码的模式将被保存在JSON作为{"pattern": "%5E%5CS%2B%40%5CS%2B%5C.%5CS%2B%24"}
。这不是理想的,但却是我能找到的避免解析问题的最不痛苦的方法。
为了从JSON中提取正则表达式模式字符串并转换为正则表达式文字值,我在模式上使用decodeURIComponent()
,然后使用new RegExp()
构造函数创建正则表达式文字。
// patternValue = /^'S+@'S+'.'S+$/
const json = JSON.parse(`{"pattern": "${encodeURIComponent(patternValue)}" }`); // {"pattern": "%5E%5CS%2B%40%5CS%2B%5C.%5CS%2B%24" }
const dp = decodeURIComponent(json.pattern);
const regExString = new RegExp(dp);
console.log(regExString); // /^'S+@'S+'.'S+$/
以上所有答案都是正确的,您可以将这部分代码保存为字符串,然后执行eval()
var sCode = 'var oFoo = {"regexp": new RegExp("/^http:'/'//"), "fun": function() {}}';
eval(sCode);
console.log(oFoo);
- js.erb文件中提供给RegExp构造函数的标志无效
- Javascript RegExp 与构造函数和文字不同的结果
- Javascript regexp 测试行为与函数
- Javascript 字符串使用 regExp 和 replacer 函数替换
- 单个函数中有多个RegExp
- 使用RegExp构造函数的具有可变模式的JavaScript正则表达式
- RegExp的exec()函数和String的match()函数有什么区别
- 我可以在JSON存储RegExp和函数
- 防止在JavaScript中污染RegExp构造函数的属性
- 何时使用RegExp构造函数vs正则表达式文本
- RegExp构造函数属性输入
- Javascript regExp - replace函数应该决定不替换匹配的字符串,以便让其他括号内的子匹配字符串与匹
- RegExp不是一个函数
- JS Regexp替换"illegal"字符来创建PHP函数名
- 通过对象匹配Javascript regexp中的空白,通过regexp构造函数创建
- 未捕获的SyntaxError:提供给RegExp构造函数的无效标志'usuario'
- 使用RegExp函数
- 转义字符串用于高亮显示函数时出错(js -regexp)
- RegExp替换函数中的反向引用不起作用
- 匹配字符串“/$"在RegExp构造函数中