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

标签 javascript node.js sails.js protocol-buffers

我正在使用Protobuf.js为 sails.js 编写一个钩子(Hook),以便能够通过 socket.io 发送由 Protocol Buffer 编码的消息。

假设我有一个原型(prototype)方案 Message.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' 
};

我有一个sails hook与代码:

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

我无法通过data直接这样:protoModels[protobufSchemeName].encode(data)因为它会导致错误:this+"#"+keyOrObj+" is not a field ,因为数据包含额外的字段;

所以问题来了:保存到 dataToSend 最简单且正确的方法是什么?仅限方案中的字段 ( Message.proto )?

附注我知道应该有 Reflection 的东西他们说你可以这样做:

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

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

最佳答案

我们仍然有一个构建器,因此解决方案与 example 中的解决方案完全相同:

...
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();
        }
    }

另一种方法是重写发射/广播方法,就像我在下面的钩子(Hook)中所做的那样:

附注如果有人觉得这有用:

我做了一个Protobuf Serialization Hook对于 Sails.js。欢迎贡献!

关于javascript - ProtoBuf.js 如何在编码对象时过滤额外字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33168640/

相关文章:

javascript - 重写此正则表达式而不使用 lookbehind - JS 的正则表达式无效

javascript 子类 node.js 表达方法来添加通用功能?

node.js - 如何测量 Sails.js 请求/响应时间

javascript - 我的 sails.js Passport.js 实现中出现 InternalOAuthError 的原因是什么?

javascript - 如何通过 Javascript 从 div 添加/删除类?

javascript - 如何通过类名获取嵌套 div 中的元素?

javascript - 使用 Javascript 显示 HTML 中的值

node.js - 如果 TCP 服务器(nodejs)发送没有分隔符的数据,TCP 客户端(golang)如何知道数据何时结束 "\n"

javascript - 如何计算数组中两个有效数字之间的零值?

javascript - 如何将 JSON 数组转换为 JSON 对象?