如何扩展EJSON以便序列化RegEx客户端 - 服务器交互? [英] How to extend EJSON to serialize RegEx for Meteor Client-Server interactions?

查看:161
本文介绍了如何扩展EJSON以便序列化RegEx客户端 - 服务器交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个任意(E)JSON,创建和发送通过线从客户端到服务器在我的Meteor应用程序。它使用 RegExp 对象将结果归零:

I have an arbitrary (E)JSON that gets created and sent over the wire from client to server in my Meteor app. It uses RegExp objects to zero-in on results:

# on the client
selector = 
  "roles.user": { "$ne": null } 
  "profile.email": /^admin@/gi 

所有在客户端都是dandy罚款,但如果我通过 Meteor.call传递给服务器 Meteor.subscribe ,结果(E)JSON采用以下形式:

All is dandy fine on the client side, but if I pass this to the server via Meteor.call or Meteor.subscribe, the resulting (E)JSON takes this form:

# on the server
selector =
  "roles.user": { "$ne": null }
  "profile.email": {}

...和某个工程师在内部消磨一点。

...and somewhere an engineer dies a little on the inside.

Web上有很多资源解释为什么RegEx是不可通过 JSON.stringify / JSON.parse 或等效的 EJSON 方法。

There are plenty of resources on the Web explaining why RegEx is unserializable via JSON.stringify/JSON.parse or the equivalent EJSON methods.

我不相信RegEx序列化是不可能的。那么如何做呢?

I'm not convinced RegEx serialization is impossible. So how can it be done?

推荐答案

查看 this HowTo and The Meteor EJSON Docs ,我们可以使用 EJSON.addType 方法来序列化RegEx。

After reviewing this HowTo and the Meteor EJSON Docs, we may serialize RegEx using the EJSON.addType method.

扩展RegExp - 使用方法 EJSON.addType 提供RegExp以实现。

Extend RegExp - Provide RegExp with the methods EJSON.addType requires for implementation.

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 中定义的对象。

Call EJSON.addType - Do this anywhere. It's best to make it available to client AND server though. This is going to deserialize the object defined in toJSONValue above.

EJSON.addType "RegExp", (value) ->
  return new RegExp(value['regex'], value['options'])

在您的控制台中测试 - 不要接受我的话。看自己。

Test In Your Console - Don't take my word for it. See for yourself.

> o = EJSON.stringify(/^Mooo/ig)
"{"$type":"RegExp","$value":{"regex":"^Mooo","options":"ig"}}"
> EJSON.parse(o)
/^Mooo/gi

在客户端和服务器上进行序列化和解析,能够通过线路传递,保存在会话中,甚至可能存储在查询集合中!

And there you have a RegExp being serialized and parsed on client and server, able to be passed in over the wire, saved in a Session, and even possibly stored in a Collection of queries!

EDIT to addess IE10 +错误:在严格模式下不允许分配只读属性在注释中感谢@Tim Fletcher

EDIT to addess IE10+ Error: Assignment to read-only properties is not allowed in strict mode Courtesy of @Tim Fletcher in the comments

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

这篇关于如何扩展EJSON以便序列化RegEx客户端 - 服务器交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆