If an existing message type no longer meets all your needs – for example, you'd like the message format to have an extra field – but you'd still like to use code created with the old format, don't worry! It's very simple to update message types without breaking any of your existing code. Just remember the following rules:
如果一个已有的消息类型不能再满足你所有的需求——比如,你想要消息形式有一个补添的(extra)字段——但你还想使用用旧形式创建的代码,别担心!更新消息类型而不破坏你的任何现有代码是非常简单的。只需记住下面的规则:
-
Don't change the field numbers for any existing fields.
-
不要改变任何现有字段的字段编号。
-
If you add new fields, any messages serialized by code using your "old" message format can still be parsed by your new generated code. You should keep in mind the default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. See the Unknown Fields section for details.
-
如果你添加了新的字段,任何使用你的“老的”消息形式的代码来序列化的消息,仍然能被你新的生成的代码解析。你应该在脑海里记着这些元素(按指新添加的字段的类型)的默认值,以使新代码能够恰当地同由旧代码生成的消息交互。同样地,由你的新代码创建的消息,也可以被你的旧代码解析:解析时,旧的二进制只是简单地忽略了新的字段。请查看未知字段部分来获取更多细节。
-
Fields can be removed, as long as the field number is not used again in your updated message type. You may want to rename the field instead, perhaps adding the prefix "OBSOLETE_", or make the field number reserved, so that future users of your .proto can't accidentally reuse the number.
-
只要字段编号在你更新过的消息类型中不再使用,字段就可以移除。你可能想通过重命名来代替(上面的做法),那就添加一个 “OBSOLETE_” 的前缀,或将字段编号标记为
reserved
,这么着之后,你的.proto
文件未来的用户们才不会意外地重新用到这个编号。 -
int32, uint32, int64, uint64, and bool are all compatible – this means you can change a field from one of these types to another without breaking forwards- or backwards-compatibility. If a number is parsed from the wire which doesn't fit in the corresponding type, you will get the same effect as if you had cast the number to that type in C++ (e.g. if a 64-bit number is read as an int32, it will be truncated to 32 bits).
-
int32,uint32,int64,uint64,还有 bool,它们全是相互兼容的——这意味着你可以在不破坏向前或向后兼容性的前提下,把一个字段的类型,从它们中的某一个改换为另一个。如果从通信线路上解析出来的一个数字并不符合相应的类型,你会得到同样的效果——好像你已经把那个数字铸改(cast)成了 C++ 中的类型一样(例如,如果一个 64 位的数字按照一个 int32 来读取,它就会被削截(truncate)到 32 位)。
(上面一段最后一句翻译的不好。)
-
sint32 and sint64 are compatible with each other but are not compatible with the other integer types.
-
sint32
和sint64
相互兼容,但和其他整数类型不兼容。 -
string and bytes are compatible as long as the bytes are valid UTF-8.
-
只要字节码是有效的 UTF-8,
string
和bytes
就是兼容的。 -
Embedded messages are compatible with bytes if the bytes contain an encoded version of the message.
-
如果字节码包含了一个编码过的版本的消息,那它与嵌入消息是兼容的。
-
fixed32 is compatible with sfixed32, and fixed64 with sfixed64.
-
fixed32
和sfixed32
是兼容的,fixed64
和sfixed64
一样道理。 -
For string, bytes, and message fields, optional is compatible with repeated. Given serialized data of a repeated field as input, clients that expect this field to be optional will take the last input value if it's a primitive type field or merge all input elements if it's a message type field. Note that this is not generally safe for numeric types, including bools and enums. Repeated fields of numeric types can be serialized in the packed format, which will not be parsed correctly when an optional field is expected.
-
对于
string
,bytes
,和消息字段来说,optional
与repeated
是兼容的。给定一个可重复字段的序列化后的数据作为输入,期待这个字段是optional
的客户端会采用最后一个输入值——如果字段是原始类型的,或合并所有输入元素——如果字段是消息类型的。注意,对数字类型——包括布尔和枚举——来说,这条通常是不安全的。数字类型的可重复字段可被以 packed 格式来序列化,当期待的是一个可选字段时,(这个可重复字段)就不会被正确解析。[注]
【注上段的意思是,假设我们输入一个序列化的可重复字段的数据,客户端想要的这个字段的类型却是可选的(因为它说可选与可重复是兼容的,下文就具体说如何处理),如果这个可重复字段的类型(输入端的类型)是原始类型的,客户端最终得到的是:可重复字段数据(即数组)的最后一个元素,如果这个可重复字段是消息类型的,客户端得到的就是把所有消息合并后的一个值(看不太懂它怎么合并)。后半段解释了因为数字类型的可重复字段会用特殊的 packed 格式来序列化,所以如果把它当作输入,也想解析成可选字段的值的话,就没办法正确解析。所以什么意思呢?当我们说可选与可重复是兼容的时候,所有数字类型的类型,都不支持的。】
-
enum is compatible with int32, uint32, int64, and uint64 in terms of wire format (note that values will be truncated if they don't fit). However be aware that client code may treat them differently when the message is deserialized: for example, unrecognized proto3 enum types will be preserved in the message, but how this is represented when the message is deserialized is language-dependent. Int fields always just preserve their value.
-
就通信线路格式而言(注意,值如果不符合它们的类型,就会被截削),
枚举
与int32
、uint32
、int64
、uint64
都兼容。但是,请意识到,在消息反序列化时,客户端代码可能会不同地处理它们:例如,未能识别的 proto3枚举
类型会保留在消息中,但它会被如何呈现,却是因语言而异的。 -
Changing a single value into a member of a new oneof is safe and binary compatible. Moving multiple fields into a new oneof may be safe if you are sure that no code sets more than one at a time. Moving any fields into an existing oneof is not safe.
-
将一个单值(single value)改为一个新的
oneof
的一个成员,是安全而且二进制兼容的。如果你确定没有代码会一次性设置多于一个的字段,那么移动多条字段到一个新的oneof
里面可能是安全的。移动若干字段到一个现有的oneof
中是不安全的。