0
# Message System
1
2
The Message system provides the core functionality for defining protocol buffer messages that behave like native Python classes. Messages automatically handle serialization, deserialization, type conversion, and provide a Pythonic interface for working with structured data.
3
4
## Capabilities
5
6
### Message Definition
7
8
Define protocol buffer messages as Python classes using the Message base class. The metaclass automatically generates protocol buffer descriptors and provides seamless integration.
9
10
```python { .api }
11
class Message(metaclass=MessageMeta):
12
"""
13
Abstract base class for protocol buffer messages.
14
15
Args:
16
mapping (Union[dict, Message]): A dictionary or message to be used to
17
determine the values for this message.
18
ignore_unknown_fields (Optional[bool]): If True, do not raise errors for
19
unknown fields. Only applied if mapping is a mapping type or there
20
are keyword parameters.
21
kwargs (dict): Keys and values corresponding to the fields of the message.
22
"""
23
def __init__(self, mapping=None, *, ignore_unknown_fields=False, **kwargs): ...
24
```
25
26
Example usage:
27
28
```python
29
class Address(proto.Message):
30
street = proto.Field(proto.STRING, number=1)
31
city = proto.Field(proto.STRING, number=2)
32
zip_code = proto.Field(proto.STRING, number=3)
33
34
class Person(proto.Message):
35
name = proto.Field(proto.STRING, number=1)
36
age = proto.Field(proto.INT32, number=2)
37
address = proto.Field(Address, number=3)
38
39
# Create message instances
40
person = Person(
41
name="John Doe",
42
age=25,
43
address={"street": "123 Main St", "city": "Anytown", "zip_code": "12345"}
44
)
45
46
# Or using keyword arguments
47
person = Person(name="Jane Doe", age=30)
48
```
49
50
### Protocol Buffer Integration
51
52
Access the underlying protocol buffer objects and perform low-level operations when needed.
53
54
```python { .api }
55
@classmethod
56
def pb(cls, obj=None, *, coerce: bool = False):
57
"""
58
Return the underlying protobuf Message class or instance.
59
60
Args:
61
obj: If provided, and an instance of cls, return the underlying
62
protobuf instance.
63
coerce (bool): If provided, will attempt to coerce obj to cls
64
if it is not already an instance.
65
66
Returns:
67
The protobuf class (if obj is None) or protobuf instance
68
"""
69
70
@classmethod
71
def wrap(cls, pb):
72
"""
73
Return a Message object that shallowly wraps the descriptor.
74
75
Args:
76
pb: A protocol buffer object, such as would be returned by pb().
77
78
Returns:
79
Message instance wrapping the protobuf object
80
"""
81
```
82
83
Example usage:
84
85
```python
86
# Get the underlying protobuf class
87
pb_class = Person.pb()
88
89
# Get the underlying protobuf instance
90
pb_instance = Person.pb(person)
91
92
# Wrap an existing protobuf object
93
wrapped = Person.wrap(pb_instance)
94
```
95
96
### Serialization and Deserialization
97
98
Convert messages to and from binary format for storage and transmission.
99
100
```python { .api }
101
@classmethod
102
def serialize(cls, instance) -> bytes:
103
"""
104
Return the serialized proto.
105
106
Args:
107
instance: An instance of this message type, or something compatible
108
(accepted by the type's constructor).
109
110
Returns:
111
bytes: The serialized representation of the protocol buffer.
112
"""
113
114
@classmethod
115
def deserialize(cls, payload: bytes) -> "Message":
116
"""
117
Given a serialized proto, deserialize it into a Message instance.
118
119
Args:
120
payload (bytes): The serialized proto.
121
122
Returns:
123
Message: An instance of the message class against which this
124
method was called.
125
"""
126
```
127
128
Example usage:
129
130
```python
131
# Serialize to bytes
132
data = Person.serialize(person)
133
134
# Deserialize from bytes
135
person_copy = Person.deserialize(data)
136
```
137
138
### JSON Conversion
139
140
Convert messages to and from JSON format with extensive customization options.
141
142
```python { .api }
143
@classmethod
144
def to_json(cls, instance, *, use_integers_for_enums=True,
145
including_default_value_fields=None, preserving_proto_field_name=False,
146
sort_keys=False, indent=2, float_precision=None,
147
always_print_fields_with_no_presence=None) -> str:
148
"""
149
Given a message instance, serialize it to json.
150
151
Args:
152
instance: An instance of this message type, or something compatible.
153
use_integers_for_enums (Optional[bool]): Whether enum values should be
154
represented by strings (False) or integers (True). Default is True.
155
including_default_value_fields (Optional[bool]): If True, include fields
156
that are set to their default values in the output.
157
preserving_proto_field_name (Optional[bool]): Whether field name
158
representations preserve proto case (snake_case) or use lowerCamelCase.
159
sort_keys (Optional[bool]): If True, then the output will be sorted by field names.
160
indent (Optional[int]): The JSON object will be pretty-printed with this indent level.
161
float_precision (Optional[int]): If set, use this to specify float field valid digits.
162
always_print_fields_with_no_presence (Optional[bool]): If True, fields without
163
presence will always be serialized.
164
165
Returns:
166
str: The json string representation of the protocol buffer.
167
"""
168
169
@classmethod
170
def from_json(cls, payload, *, ignore_unknown_fields=False) -> "Message":
171
"""
172
Given a json string representing an instance, parse it into a message.
173
174
Args:
175
payload: A json string representing a message.
176
ignore_unknown_fields (Optional[bool]): If True, do not raise errors
177
for unknown fields.
178
179
Returns:
180
Message: An instance of the message class against which this method was called.
181
"""
182
```
183
184
Example usage:
185
186
```python
187
# Convert to JSON
188
json_str = Person.to_json(person, indent=4, sort_keys=True)
189
190
# Parse from JSON
191
person_from_json = Person.from_json(json_str)
192
```
193
194
### Dictionary Conversion
195
196
Convert messages to and from Python dictionaries for easy integration with Python data structures.
197
198
```python { .api }
199
@classmethod
200
def to_dict(cls, instance, *, use_integers_for_enums=True,
201
preserving_proto_field_name=True, including_default_value_fields=None,
202
float_precision=None, always_print_fields_with_no_presence=None) -> dict:
203
"""
204
Given a message instance, return its representation as a python dict.
205
206
Args:
207
instance: An instance of this message type, or something compatible.
208
use_integers_for_enums (Optional[bool]): Whether enum values should be
209
represented by strings (False) or integers (True). Default is True.
210
preserving_proto_field_name (Optional[bool]): Whether field name
211
representations preserve proto case (snake_case) or use lowerCamelCase.
212
including_default_value_fields (Optional[bool]): If True, include fields
213
that are set to their default values in the output.
214
float_precision (Optional[int]): If set, use this to specify float field valid digits.
215
always_print_fields_with_no_presence (Optional[bool]): If True, fields without
216
presence will always be serialized.
217
218
Returns:
219
dict: A representation of the protocol buffer using pythonic data structures.
220
"""
221
```
222
223
Example usage:
224
225
```python
226
# Convert to dictionary
227
person_dict = Person.to_dict(person)
228
229
# Create from dictionary
230
person_from_dict = Person(person_dict)
231
```
232
233
### Message Copying
234
235
Copy data from other messages or dictionaries into existing message instances.
236
237
```python { .api }
238
@classmethod
239
def copy_from(cls, instance, other):
240
"""
241
Equivalent for protobuf.Message.CopyFrom.
242
243
Args:
244
instance: An instance of this message type
245
other (Union[dict, Message]): A dictionary or message to reinitialize
246
the values for this message.
247
"""
248
```
249
250
Example usage:
251
252
```python
253
person1 = Person(name="Alice", age=25)
254
person2 = Person()
255
256
# Copy data from another message
257
Person.copy_from(person2, person1)
258
259
# Copy data from a dictionary
260
Person.copy_from(person2, {"name": "Bob", "age": 30})
261
```
262
263
## Message Behavior
264
265
Messages behave like native Python objects with standard Python protocols:
266
267
- **Attribute access**: `person.name`, `person.age`
268
- **Containment**: `'name' in person` checks if field was set
269
- **Boolean conversion**: `bool(person)` returns True if any field is set
270
- **Equality**: `person1 == person2` compares message contents
271
- **String representation**: `str(person)` and `repr(person)` show message contents
272
- **Attribute setting**: `person.name = "New Name"`
273
- **Attribute deletion**: `del person.name` clears the field