首先用一幅图来指出protobuf在显示不同方法之间的关系以及有效消息的概念:在这里暂时不需要理解,后面我们会一点一点解释。

主要注意的是,我们在介绍各个不同的方法的时候,Message指的是一个任意的消息类:
为了说明问题,我的demo代码用浏览器端的代码来演示:
<!doctype html>
<head>
<style>
</style>
<script src="js/protobuf.js"></script>
</head>
<body>
<script>
var jsonDescriptor = {
"nested": {
"awesomepackage": {
"nested": {
"AwesomeMessage": {
"fields": {
"awesomeField": {
"type": "string",
"id": 1
}
}
}
}
}
}
};
var root = protobuf.Root.fromJSON(jsonDescriptor);
console.log('root:',root);
// Obtain a message type
var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
console.log('AwesomeMessage :',AwesomeMessage);
// Exemplary payload
var payload = { awesomeField: "AwesomeString" };
// Verify the payload if necessary (i.e. when possibly incomplete or invalid)
var errMsg = AwesomeMessage.verify(payload);
if (errMsg)
throw Error(errMsg);
// Create a new message
var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary
console.log('message :',message);
// Encode a message to an Uint8Array (browser) or Buffer (node)
var buffer = AwesomeMessage.encode(message).finish();
console.log('buffer :',buffer);
// ... do something with buffer
// Decode an Uint8Array (browser) or Buffer (node) to a message
var message = AwesomeMessage.decode(buffer);
console.log('decode message :',message);
// ... do something with message
// If the application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.
// Maybe convert the message back to a plain object
var object = AwesomeMessage.toObject(message, {
longs: String,
enums: String,
bytes: String,
// see ConversionOptions
});
console.log('origin object :',object);
</script>
</body>
</html>
这段代码的简单输出如下:
我们首先看这一部分,这一部分用JSON对象描述符来初始化root实例:
protobuf.Root.fromJSON(descriptor)
var root = protobuf.Root.fromJSON(jsonDescriptor);
console.log('root:',root);
可以看到我们的消息AwesomeMessage
已经实例化好了,而且这个类型包含了一些基本的方法,比如:encode,
decode,fromObject,toObject,verify
。这些方法和我们最上面图展示的方法是不是很类似。
Message.verify(payload)
我们先来看Message.verify(payload)
我们的代码首先通过var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
获得自己定义的消息类型。然后创建一个消息,最后调用var errMsg = AwesomeMessage.verify(payload);
注意,如果这里的消息有问题,比如多了一个字段,或者字段类型不正确,则会返回具体的错误信息,这样可以验证这个消息是不合法的。
Message.create(object)和Message.encode(message)
我们再来看Message.create(object)
我们的代码使用var message = AwesomeMessage.create(payload);
创建了一个消息对象实例,然后调用var buffer = AwesomeMessage.encode(message).finish();
实现了消息到Uint8Array的转化。如下图所示:
Message.decode(buffer)和Message.toObject(message)
我们通过调用var message = AwesomeMessage.decode(buffer);
将buffer转化为了具体的消息实例(AwesomeMessage),以及
var object = AwesomeMessage.toObject(message, {
longs: String,
enums: String,
bytes: String,
// see ConversionOptions
});
这段代码最后将消息对象转化为具体的Object对象。
以上就是一个protobuf从编码到解码的一个完整的流程,不难看出,这个流程还是比较清晰的,不过这里给大家伙留下了一个疑问?
为什么要采用这种编码和解码的方式呢?或者说它的