如何扩展 EJSON 以序列化 RegEx 以进行 Meteor 客户端-服务器交互?
Posted
技术标签:
【中文标题】如何扩展 EJSON 以序列化 RegEx 以进行 Meteor 客户端-服务器交互?【英文标题】:How to extend EJSON to serialize RegEx for Meteor Client-Server interactions? 【发布时间】:2016-06-03 15:11:35 【问题描述】:我有一个任意的 (E)JSON,它在我的 Meteor 应用程序中创建并通过线路从客户端发送到服务器。它使用RegExp
对象将结果归零:
# on the client
selector =
"roles.user": "$ne": null
"profile.email": /^admin@/gi
在客户端一切都很好,但是如果我通过Meteor.call
或Meteor.subscribe
将其传递给服务器,则生成的 (E)JSON 采用以下形式:
# on the server
selector =
"roles.user": "$ne": null
"profile.email":
...在某个地方,一位工程师在内心深处死去。
网上有很多资源可以解释为什么 RegEx 无法通过 JSON.stringify
/JSON.parse
或等效的 EJSON
方法进行序列化。
我不相信 RegEx 序列化是不可能的。那么怎么做呢?
【问题讨论】:
【参考方案1】:查看this HowTo和the Meteor EJSON Docs后,我们可以使用EJSON.addType
方法序列化RegEx。
Extend RegExp - 为 RegExp 提供 EJSON.addType
实现所需的方法。
RegExp::options = ->
opts = []
opts.push 'g' if @global
opts.push 'i' if @ignoreCase
opts.push 'm' if @multiline
return opts.join('')
RegExp::clone = ->
self = @
return new RegExp(self.source, self.options())
RegExp::equals = (other) ->
self = @
if other isnt instanceOf RegExp
return false
return EJSON.stringify(self) is EJSON.stringify(other)
RegExp::typeName = ->
return "RegExp"
RegExp::toJSONValue = ->
self = @
return
'regex': self.source
'options': self.options()
调用 EJSON.addType - 在任何地方执行此操作。最好让它对客户端和服务器可用。这将反序列化上面toJSONValue
中定义的对象。
EJSON.addType "RegExp", (value) ->
return new RegExp(value['regex'], value['options'])
在您的控制台中测试 - 不要相信我的话。自己看吧。
> o = EJSON.stringify(/^Mooo/ig)
""$type":"RegExp","$value":"regex":"^Mooo","options":"ig""
> EJSON.parse(o)
/^Mooo/gi
你有一个正则表达式在客户端和服务器上被序列化和解析,能够通过网络传递,保存在会话中,甚至可能存储在查询集合中!
编辑添加 IE10+ 错误:在严格模式下不允许分配给只读属性由 cmets 中的 @Tim Fletcher 提供
import EJSON from 'meteor/ejson';
function getOptions(self)
const opts = [];
if (self.global) opts.push('g');
if (self.ignoreCase) opts.push('i');
if (self.multiline) opts.push('m');
return opts.join('');
RegExp.prototype.clone = function clone()
return new RegExp(this.source, getOptions(this));
;
RegExp.prototype.equals = function equals(other)
if (!(other instanceof RegExp)) return false;
return EJSON.stringify(this) === EJSON.stringify(other);
;
RegExp.prototype.typeName = function typeName()
return 'RegExp';
;
RegExp.prototype.toJSONValue = function toJSONValue()
return regex: this.source, options: getOptions(this) ;
;
EJSON.addType('RegExp', value => new RegExp(value.regex, value.options));
【讨论】:
感谢您的回答。这在 Chrome 中确实很有效,但在 IE 10+ 中使用Assignment to read-only properties is not allowed in strict mode
杀死了 Meteor。我用这个版本(ES6)修复了它gist.github.com/TimFletcher/1fc43b36a2710f09895613ecdd7c39a7【参考方案2】:
有一个更简单的解决方案:
通过.toString()
对您的正则表达式进行字符串化,将其发送到服务器,然后将其解析回正则表达式。
【讨论】:
以上是关于如何扩展 EJSON 以序列化 RegEx 以进行 Meteor 客户端-服务器交互?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式处理英文缩写 [Regex, JS, Ruby]
使用 Linq 和 Regex 比较 2 个字符串数组以进行部分匹配