ProtoBuf.js如何在编码对象时过滤额外的字段

我正在使用Protobuf.js为sails.js编写一个钩子,以便能够通过socket.io发送由协议缓冲区编码的消息。

说我有一个原型schemeMessage.proto

 message Message{ required string message = 1; optional string user = 2; optional int32 id = 3; } 

我从数据库中获取一个对象作为data

 data = { message: 'Hello', user: 'johnDoe', id: 90, createdAt: '2015-10-16T10:15:39.837Z', updatedAt: '2015-10-16T10:15:39.837Z' }; 

我有一个代码:

 var ProtoBuf = require("protobufjs"), Reflect = ProtoBuf.Reflect, builder = ProtoBuf.newBuilder(), protoModels; ... // This method overrides socket.io broadcast call for sails.js models pubSub: augmentModels: function () { for (var identity in app.models) { var protobufSchemeName = app.models[identity].protobufSchemeName; // protobufSchemeName is the file name of the sheme if (protobufSchemeName) { ProtoBuf.loadProtoFile(path.join(app.config.appPath, app.config.protobuf.folder, protobufSchemeName + ".proto"), builder); app.models[identity].broadcast = function (roomName, eventName, data, socketToOmit) { var dataToSend = protoModels[protobufSchemeName].encode(???HERE???); //HERE I SHOULD PUT THE MODIFIED DATA WITH THE ONLY NECESSARY FIELDS app.sockets.broadcast(roomName, eventName, dataToSend.toBuffer(), socketToOmit); }; } protoModels = builder.build(); } } 

我不能直接以这种方式传递dataprotoModels[protobufSchemeName].encode(data)因为它会导致错误: this+"#"+keyOrObj+" is not a field ,因为数据包含额外的字段;

所以问题是 :什么是最简单和正确的方式来保存dataToSend只有scheme中的字段( Message.proto )?

PS我知道应该有反思的东西,他们说你可以这样做:

 var TPlayer = builder.lookup("Game.Player"); // instance of ProtoBuf.Reflect.Message var fields = TPlayer.getChildren(ProtoBuf.Reflect.Message.Field); // instances of ProtoBuf.Reflect.Message.Field fields.forEach(function(field) { //Filter it here }); 

但我不知道如何从protoModels到达lookup方法。 也许有办法使用Builder的 isMessageField方法来过滤data字段?

我们还有一个build造者,所以解决scheme和例子中的完全一样:

 ... augmentModels: function () { for (var identity in app.models) { var protobufSchemeName = app.models[identity].protobufSchemeName; if (protobufSchemeName) { ProtoBuf.loadProtoFile(path.join(app.config.appPath, app.config.protobuf.folder, protobufSchemeName + ".proto"), builder); app.models[identity].broadcast = function (roomName, eventName, data, socketToOmit) { var fields = builder.lookup(protobufSchemeName).getChildren(ProtoBuf.Reflect.Message.Field).map(function (f) { return f.name; }); //Here are the fieldnames of the scheme as an array var dataToSend = protoModels[protobufSchemeName].encode(_.pick(data, fields)).toBuffer(); app.sockets.broadcast(roomName, eventName, dataToSend, socketToOmit); }; } protoModels = builder.build(); } } 

另一种方法是重写发射/广播方法,就像我在下面的钩子:

PS如果有人会发现这个有用的:

我为Sails.js做了一个Protobuf序列化钩子 。 贡献是值得欢迎的!