0
# Message and Field Types
1
2
Core message functionality including field creation functions for all protobuf types, dataclass integration, and metadata handling for proper serialization and deserialization.
3
4
## Capabilities
5
6
### Message Base Class
7
8
The `Message` class serves as the base for all generated protobuf messages, providing serialization, parsing, and conversion methods.
9
10
```python { .api }
11
class Message:
12
"""
13
A protobuf message base class. Generated code inherits from this and
14
registers message fields used by serializers and parsers.
15
"""
16
17
def __bytes__(self) -> bytes:
18
"""Get the binary encoded Protobuf representation of this instance."""
19
20
def SerializeToString(self) -> bytes:
21
"""Compatibility alias for __bytes__."""
22
23
def parse(self, data: bytes) -> T:
24
"""
25
Parse the binary encoded Protobuf into this message instance.
26
Returns the instance itself for chaining.
27
"""
28
29
@classmethod
30
def FromString(cls, data: bytes) -> T:
31
"""Parse binary data into a new message instance (compatibility method)."""
32
33
def to_dict(
34
self,
35
casing: Casing = Casing.CAMEL,
36
include_default_values: bool = False
37
) -> dict:
38
"""
39
Convert message to dictionary representation for JSON serialization.
40
41
Args:
42
casing: Field name casing (CAMEL or SNAKE)
43
include_default_values: Include fields with default values
44
45
Returns:
46
Dictionary representation of the message
47
"""
48
49
def from_dict(self, value: dict) -> T:
50
"""
51
Parse key/value pairs into this message instance.
52
Returns the instance itself for chaining.
53
"""
54
55
def to_json(self, indent: Union[None, int, str] = None) -> str:
56
"""Convert message to JSON string representation."""
57
58
def from_json(self, value: Union[str, bytes]) -> T:
59
"""
60
Parse JSON into this message instance.
61
Returns the instance itself for chaining.
62
"""
63
```
64
65
### Basic Field Types
66
67
Functions to create dataclass fields with protobuf metadata for primitive types.
68
69
```python { .api }
70
def string_field(number: int, group: Optional[str] = None) -> Any:
71
"""Create a string field with the given protobuf field number."""
72
73
def bool_field(number: int, group: Optional[str] = None) -> Any:
74
"""Create a boolean field with the given protobuf field number."""
75
76
def bytes_field(number: int, group: Optional[str] = None) -> Any:
77
"""Create a bytes field with the given protobuf field number."""
78
```
79
80
### Integer Field Types
81
82
Functions to create fields for various integer types with different encoding and size characteristics.
83
84
```python { .api }
85
def int32_field(number: int, group: Optional[str] = None) -> Any:
86
"""Create a signed 32-bit integer field."""
87
88
def int64_field(number: int, group: Optional[str] = None) -> Any:
89
"""Create a signed 64-bit integer field."""
90
91
def uint32_field(number: int, group: Optional[str] = None) -> Any:
92
"""Create an unsigned 32-bit integer field."""
93
94
def uint64_field(number: int, group: Optional[str] = None) -> Any:
95
"""Create an unsigned 64-bit integer field."""
96
97
def sint32_field(number: int, group: Optional[str] = None) -> Any:
98
"""Create a signed 32-bit integer field with zigzag encoding."""
99
100
def sint64_field(number: int, group: Optional[str] = None) -> Any:
101
"""Create a signed 64-bit integer field with zigzag encoding."""
102
103
def fixed32_field(number: int, group: Optional[str] = None) -> Any:
104
"""Create a 32-bit fixed-width integer field."""
105
106
def fixed64_field(number: int, group: Optional[str] = None) -> Any:
107
"""Create a 64-bit fixed-width integer field."""
108
109
def sfixed32_field(number: int, group: Optional[str] = None) -> Any:
110
"""Create a signed 32-bit fixed-width integer field."""
111
112
def sfixed64_field(number: int, group: Optional[str] = None) -> Any:
113
"""Create a signed 64-bit fixed-width integer field."""
114
```
115
116
### Floating Point Field Types
117
118
Functions to create fields for floating-point numbers with different precision levels.
119
120
```python { .api }
121
def float_field(number: int, group: Optional[str] = None) -> Any:
122
"""Create a 32-bit floating-point field."""
123
124
def double_field(number: int, group: Optional[str] = None) -> Any:
125
"""Create a 64-bit floating-point field."""
126
```
127
128
### Complex Field Types
129
130
Functions to create fields for messages, maps, and enums.
131
132
```python { .api }
133
def message_field(
134
number: int,
135
group: Optional[str] = None,
136
wraps: Optional[str] = None
137
) -> Any:
138
"""
139
Create a nested message field.
140
141
Args:
142
number: Protobuf field number
143
group: One-of group name if this field is part of a one-of
144
wraps: Wrapped type for Google protobuf wrapper types
145
"""
146
147
def map_field(
148
number: int,
149
key_type: str,
150
value_type: str,
151
group: Optional[str] = None
152
) -> Any:
153
"""
154
Create a map field (dictionary in Python).
155
156
Args:
157
number: Protobuf field number
158
key_type: Protobuf type of map keys
159
value_type: Protobuf type of map values
160
group: One-of group name if this field is part of a one-of
161
"""
162
163
def enum_field(number: int, group: Optional[str] = None) -> Any:
164
"""Create an enumeration field."""
165
```
166
167
### Field Metadata
168
169
The `FieldMetadata` class stores protobuf-specific information about fields.
170
171
```python { .api }
172
@dataclass(frozen=True)
173
class FieldMetadata:
174
"""Stores internal metadata used for parsing & serialization."""
175
176
number: int # Protobuf field number
177
proto_type: str # Protobuf type name
178
map_types: Optional[Tuple[str, str]] = None # Map key/value types
179
group: Optional[str] = None # One-of group name
180
wraps: Optional[str] = None # Wrapped type for Google wrappers
181
182
@staticmethod
183
def get(field: dataclasses.Field) -> "FieldMetadata":
184
"""Returns the field metadata for a dataclass field."""
185
```
186
187
### Core Field Creation Function
188
189
The underlying function used by all field creation functions.
190
191
```python { .api }
192
def dataclass_field(
193
number: int,
194
proto_type: str,
195
*,
196
map_types: Optional[Tuple[str, str]] = None,
197
group: Optional[str] = None,
198
wraps: Optional[str] = None,
199
) -> dataclasses.Field:
200
"""Creates a dataclass field with attached protobuf metadata."""
201
```
202
203
## Usage Examples
204
205
### Basic Message Definition
206
207
```python
208
from dataclasses import dataclass
209
import betterproto
210
211
@dataclass
212
class Person(betterproto.Message):
213
name: str = betterproto.string_field(1)
214
age: int = betterproto.int32_field(2)
215
is_active: bool = betterproto.bool_field(3)
216
profile_picture: bytes = betterproto.bytes_field(4)
217
```
218
219
### One-of Fields
220
221
```python
222
@dataclass
223
class Contact(betterproto.Message):
224
# One-of group for contact method
225
email: str = betterproto.string_field(1, group="contact_method")
226
phone: str = betterproto.string_field(2, group="contact_method")
227
228
# Check which one-of field is set
229
contact_type, contact_value = betterproto.which_one_of(contact, "contact_method")
230
```
231
232
### Nested Messages
233
234
```python
235
@dataclass
236
class Address(betterproto.Message):
237
street: str = betterproto.string_field(1)
238
city: str = betterproto.string_field(2)
239
country: str = betterproto.string_field(3)
240
241
@dataclass
242
class Person(betterproto.Message):
243
name: str = betterproto.string_field(1)
244
address: Address = betterproto.message_field(2)
245
addresses: List[Address] = betterproto.message_field(3) # Repeated field
246
```
247
248
### Map Fields
249
250
```python
251
@dataclass
252
class PhoneBook(betterproto.Message):
253
# Map from string names to string phone numbers
254
contacts: Dict[str, str] = betterproto.map_field(1, "string", "string")
255
256
# Map from string names to Person messages
257
people: Dict[str, Person] = betterproto.map_field(2, "string", "message")
258
```
259
260
## Types
261
262
```python { .api }
263
# Protobuf type constants
264
TYPE_ENUM: str = "enum"
265
TYPE_BOOL: str = "bool"
266
TYPE_INT32: str = "int32"
267
TYPE_INT64: str = "int64"
268
TYPE_UINT32: str = "uint32"
269
TYPE_UINT64: str = "uint64"
270
TYPE_SINT32: str = "sint32"
271
TYPE_SINT64: str = "sint64"
272
TYPE_FLOAT: str = "float"
273
TYPE_DOUBLE: str = "double"
274
TYPE_FIXED32: str = "fixed32"
275
TYPE_SFIXED32: str = "sfixed32"
276
TYPE_FIXED64: str = "fixed64"
277
TYPE_SFIXED64: str = "sfixed64"
278
TYPE_STRING: str = "string"
279
TYPE_BYTES: str = "bytes"
280
TYPE_MESSAGE: str = "message"
281
TYPE_MAP: str = "map"
282
```