0
# Codec System
1
2
The BSON codec system provides flexible serialization and deserialization between Java objects and BSON documents. It includes built-in codecs for all standard Java types, support for custom POJO mapping with annotations, and an extensible framework for creating custom codecs.
3
4
## Core Codec Interfaces
5
6
### Codec Interface
7
8
```java { .api }
9
public interface Codec<T> extends Encoder<T>, Decoder<T> {
10
// Combines encoding and decoding capabilities
11
// Inherits from Encoder<T> and Decoder<T> interfaces
12
}
13
```
14
15
### Encoder Interface
16
17
```java { .api }
18
public interface Encoder<T> {
19
/**
20
* Encode an instance of the type parameter {@code T} into a BSON value.
21
* @param writer the BSON writer to encode into
22
* @param value the value to encode
23
* @param encoderContext the encoder context
24
*/
25
void encode(BsonWriter writer, T value, EncoderContext encoderContext);
26
27
/**
28
* Returns the Class instance that this encodes.
29
* @return the Class instance that this encodes
30
*/
31
Class<T> getEncoderClass();
32
}
33
```
34
35
### Decoder Interface
36
37
```java { .api }
38
public interface Decoder<T> {
39
/**
40
* Decodes a BSON value from the given reader into an instance of the type parameter {@code T}.
41
* @param reader the BSON reader
42
* @param decoderContext the decoder context
43
* @return an instance of the type parameter {@code T}
44
*/
45
T decode(BsonReader reader, DecoderContext decoderContext);
46
}
47
```
48
49
## CodecRegistry
50
51
The `CodecRegistry` manages codec lookup and provides access to codecs for specific types.
52
53
```java { .api }
54
public interface CodecRegistry {
55
/**
56
* Gets a Codec for the given Class.
57
* @param clazz the class
58
* @param <T> the type of the class
59
* @return a codec for the given class
60
* @throws CodecConfigurationException if the registry does not contain a codec for the given class
61
*/
62
<T> Codec<T> get(Class<T> clazz);
63
64
/**
65
* Gets a Codec for the given Class, or null if this registry doesn't contain a codec for the class.
66
* @param clazz the class
67
* @param registry a CodecRegistry to use as a fallback
68
* @param <T> the type of the class
69
* @return a codec for the given class, or null
70
*/
71
<T> Codec<T> get(Class<T> clazz, CodecRegistry registry);
72
}
73
```
74
75
### CodecProvider Interface
76
77
```java { .api }
78
public interface CodecProvider {
79
/**
80
* Get a Codec using the given context, which includes, most importantly, the Class for which a Codec is required.
81
* @param clazz the Class for which to get a Codec
82
* @param registry the registry to use for resolving dependent Codec instances
83
* @param <T> the type of the class
84
* @return the Codec instance, which may be null, if this source is unable to provide one for the requested Class
85
*/
86
<T> Codec<T> get(Class<T> clazz, CodecRegistry registry);
87
}
88
```
89
90
## Built-in Codec Registry
91
92
```java { .api }
93
public final class CodecRegistries {
94
/**
95
* A codec registry containing codecs for all the default supported types.
96
* @return the default codec registry
97
*/
98
public static CodecRegistry fromRegistries(CodecRegistry... registries);
99
100
/**
101
* A codec registry containing codecs for all the default supported types.
102
* @return the default codec registry
103
*/
104
public static CodecRegistry fromProviders(CodecProvider... providers);
105
106
/**
107
* A codec registry containing codecs for all the default supported types.
108
* @return the default codec registry
109
*/
110
public static CodecRegistry fromProviders(List<? extends CodecProvider> providers);
111
112
/**
113
* A codec registry containing codecs for all the default supported types.
114
* @return the default codec registry
115
*/
116
public static CodecRegistry fromCodecs(Codec<?>... codecs);
117
118
/**
119
* A codec registry containing codecs for all the default supported types.
120
* @return the default codec registry
121
*/
122
public static CodecRegistry fromCodecs(List<? extends Codec<?>> codecs);
123
124
/**
125
* Gets the default codec registry.
126
* @return the default codec registry
127
*/
128
public static CodecRegistry getDefaultCodecRegistry();
129
}
130
```
131
132
## POJO Codec Support
133
134
### PojoCodecProvider
135
136
The `PojoCodecProvider` enables automatic codec generation for Plain Old Java Objects.
137
138
```java { .api }
139
public final class PojoCodecProvider implements CodecProvider {
140
/**
141
* Create a Builder for the PojoCodecProvider.
142
* @return the Builder
143
*/
144
public static Builder builder();
145
146
/**
147
* A convenience method that automatically creates a PojoCodecProvider.
148
* @param packages the packages to scan for entities
149
* @return the PojoCodecProvider builder
150
*/
151
public static PojoCodecProvider.Builder automatic(String... packages);
152
153
public static final class Builder {
154
/**
155
* Registers a class for use in the PojoCodecProvider.
156
* @param clazz the class to register
157
* @return this
158
*/
159
public Builder register(Class<?> clazz);
160
161
/**
162
* Registers classes for use in the PojoCodecProvider.
163
* @param classes the classes to register
164
* @return this
165
*/
166
public Builder register(Class<?>... classes);
167
168
/**
169
* Sets the conventions to use when creating POJOs.
170
* @param conventions the list of conventions
171
* @return this
172
*/
173
public Builder conventions(List<Convention> conventions);
174
175
/**
176
* Sets the discriminator key to use when storing type information for polymorphic classes.
177
* @param discriminatorKey the discriminator key
178
* @return this
179
*/
180
public Builder discriminatorKey(String discriminatorKey);
181
182
/**
183
* Sets the property naming strategy to use for POJO fields.
184
* @param propertyNamingStrategy the property naming strategy
185
* @return this
186
*/
187
public Builder propertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy);
188
189
/**
190
* Build the PojoCodecProvider.
191
* @return the PojoCodecProvider
192
*/
193
public PojoCodecProvider build();
194
}
195
}
196
```
197
198
### POJO Annotations
199
200
```java { .api }
201
/**
202
* An annotation that configures the discriminator key and value for a class.
203
*/
204
@Retention(RetentionPolicy.RUNTIME)
205
@Target(ElementType.TYPE)
206
public @interface BsonDiscriminator {
207
/**
208
* The discriminator key.
209
* @return the discriminator key
210
*/
211
String key() default "";
212
213
/**
214
* The discriminator value.
215
* @return the discriminator value
216
*/
217
String value() default "";
218
}
219
220
/**
221
* An annotation that marks a field or property to be ignored when encoding/decoding.
222
*/
223
@Retention(RetentionPolicy.RUNTIME)
224
@Target({ElementType.METHOD, ElementType.FIELD})
225
public @interface BsonIgnore {
226
}
227
228
/**
229
* An annotation that specifies the field name to use when encoding/decoding.
230
*/
231
@Retention(RetentionPolicy.RUNTIME)
232
@Target({ElementType.METHOD, ElementType.FIELD})
233
public @interface BsonProperty {
234
/**
235
* The name of the field in the BSON document.
236
* @return the name of the field
237
*/
238
String value();
239
240
/**
241
* Whether to use the discriminator as a property in the BSON document when writing.
242
* @return true if the discriminator should be used as a property
243
*/
244
boolean useDiscriminator() default false;
245
}
246
247
/**
248
* An annotation that marks a field or property as the id property.
249
*/
250
@Retention(RetentionPolicy.RUNTIME)
251
@Target({ElementType.METHOD, ElementType.FIELD})
252
public @interface BsonId {
253
}
254
255
/**
256
* An annotation that marks a constructor or static factory method as the creator to use when deserializing.
257
*/
258
@Retention(RetentionPolicy.RUNTIME)
259
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
260
public @interface BsonCreator {
261
}
262
263
/**
264
* An annotation that marks a parameter in a creator as a property.
265
*/
266
@Retention(RetentionPolicy.RUNTIME)
267
@Target(ElementType.PARAMETER)
268
public @interface BsonProperty {
269
/**
270
* The property name.
271
* @return the property name
272
*/
273
String value();
274
}
275
```
276
277
## Built-in Codecs
278
279
### Basic Type Codecs
280
281
```java { .api }
282
public class StringCodec implements Codec<String> {
283
public void encode(BsonWriter writer, String value, EncoderContext encoderContext);
284
public String decode(BsonReader reader, DecoderContext decoderContext);
285
public Class<String> getEncoderClass();
286
}
287
288
public class IntegerCodec implements Codec<Integer> {
289
public void encode(BsonWriter writer, Integer value, EncoderContext encoderContext);
290
public Integer decode(BsonReader reader, DecoderContext decoderContext);
291
public Class<Integer> getEncoderClass();
292
}
293
294
public class LongCodec implements Codec<Long> {
295
public void encode(BsonWriter writer, Long value, EncoderContext encoderContext);
296
public Long decode(BsonReader reader, DecoderContext decoderContext);
297
public Class<Long> getEncoderClass();
298
}
299
300
public class DoubleCodec implements Codec<Double> {
301
public void encode(BsonWriter writer, Double value, EncoderContext encoderContext);
302
public Double decode(BsonReader reader, DecoderContext decoderContext);
303
public Class<Double> getEncoderClass();
304
}
305
306
public class BooleanCodec implements Codec<Boolean> {
307
public void encode(BsonWriter writer, Boolean value, EncoderContext encoderContext);
308
public Boolean decode(BsonReader reader, DecoderContext decoderContext);
309
public Class<Boolean> getEncoderClass();
310
}
311
```
312
313
### Collection Codecs
314
315
```java { .api }
316
public class ListCodec<T> implements Codec<List<T>> {
317
public ListCodec(Class<T> clazz, CodecRegistry codecRegistry);
318
public ListCodec(Class<T> clazz, Codec<T> codec);
319
320
public void encode(BsonWriter writer, List<T> list, EncoderContext encoderContext);
321
public List<T> decode(BsonReader reader, DecoderContext decoderContext);
322
public Class<List<T>> getEncoderClass();
323
}
324
325
public class MapCodec implements Codec<Map<String, Object>> {
326
public MapCodec();
327
public MapCodec(CodecRegistry codecRegistry);
328
329
public void encode(BsonWriter writer, Map<String, Object> map, EncoderContext encoderContext);
330
public Map<String, Object> decode(BsonReader reader, DecoderContext decoderContext);
331
public Class<Map<String, Object>> getEncoderClass();
332
}
333
```
334
335
### BSON Type Codecs
336
337
```java { .api }
338
public class BsonDocumentCodec implements CollectibleCodec<BsonDocument> {
339
public void encode(BsonWriter writer, BsonDocument document, EncoderContext encoderContext);
340
public BsonDocument decode(BsonReader reader, DecoderContext decoderContext);
341
public Class<BsonDocument> getEncoderClass();
342
public BsonDocument generateIdIfAbsentFromDocument(BsonDocument document);
343
public boolean documentHasId(BsonDocument document);
344
public BsonValue getDocumentId(BsonDocument document);
345
}
346
347
public class BsonArrayCodec implements Codec<BsonArray> {
348
public void encode(BsonWriter writer, BsonArray array, EncoderContext encoderContext);
349
public BsonArray decode(BsonReader reader, DecoderContext decoderContext);
350
public Class<BsonArray> getEncoderClass();
351
}
352
```
353
354
### UUID Representation
355
356
```java { .api }
357
public enum UuidRepresentation {
358
/**
359
* The canonical representation of UUID.
360
*/
361
STANDARD,
362
363
/**
364
* The legacy representation of UUID used by the C# driver.
365
*/
366
C_SHARP_LEGACY,
367
368
/**
369
* The legacy representation of UUID used by the Java driver.
370
*/
371
JAVA_LEGACY,
372
373
/**
374
* The legacy representation of UUID used by the Python driver.
375
*/
376
PYTHON_LEGACY,
377
378
/**
379
* An unspecified representation of UUID.
380
*/
381
UNSPECIFIED
382
}
383
384
public class UuidCodec implements Codec<UUID> {
385
public UuidCodec();
386
public UuidCodec(UuidRepresentation uuidRepresentation);
387
388
public void encode(BsonWriter writer, UUID value, EncoderContext encoderContext);
389
public UUID decode(BsonReader reader, DecoderContext decoderContext);
390
public Class<UUID> getEncoderClass();
391
public UuidRepresentation getUuidRepresentation();
392
}
393
```
394
395
## Encoder and Decoder Contexts
396
397
```java { .api }
398
public final class EncoderContext {
399
/**
400
* Create a builder.
401
* @return the builder
402
*/
403
public static Builder builder();
404
405
/**
406
* Returns true if the encoder should encode a value as a document that includes an _id if the value is missing one.
407
* @return true if the encoder should encode a collectible document
408
*/
409
public boolean isEncodingCollectibleDocument();
410
411
/**
412
* Create an encoder context that is a child of this.
413
* @return the child encoder context
414
*/
415
public EncoderContext getChildContext();
416
417
public static final class Builder {
418
/**
419
* Set to true if the value to be encoded is a document that should be handled as a collectible document.
420
* @param encodingCollectibleDocument true if the value to be encoded is a collectible document
421
* @return this
422
*/
423
public Builder isEncodingCollectibleDocument(boolean encodingCollectibleDocument);
424
425
/**
426
* Build the encoder context.
427
* @return the encoder context
428
*/
429
public EncoderContext build();
430
}
431
}
432
433
public final class DecoderContext {
434
/**
435
* Create a builder.
436
* @return the builder
437
*/
438
public static Builder builder();
439
440
/**
441
* Create a decoder context that is a child of this.
442
* @return the child decoder context
443
*/
444
public DecoderContext getChildContext();
445
446
public static final class Builder {
447
/**
448
* Build the decoder context.
449
* @return the decoder context
450
*/
451
public DecoderContext build();
452
}
453
}
454
```
455
456
## Usage Examples
457
458
### Basic Codec Usage
459
460
```java
461
import org.bson.codecs.*;
462
import org.bson.*;
463
import org.bson.io.BasicOutputBuffer;
464
465
// Get the default codec registry
466
CodecRegistry codecRegistry = CodecRegistries.getDefaultCodecRegistry();
467
468
// Get a codec for a specific type
469
Codec<String> stringCodec = codecRegistry.get(String.class);
470
471
// Encode a string
472
BasicOutputBuffer buffer = new BasicOutputBuffer();
473
BsonBinaryWriter writer = new BsonBinaryWriter(buffer);
474
writer.writeStartDocument();
475
writer.writeName("message");
476
stringCodec.encode(writer, "Hello, World!", EncoderContext.builder().build());
477
writer.writeEndDocument();
478
writer.close();
479
480
// Decode the string back
481
BsonBinaryReader reader = new BsonBinaryReader(ByteBuffer.wrap(buffer.toByteArray()));
482
reader.readStartDocument();
483
reader.readName(); // "message"
484
String decoded = stringCodec.decode(reader, DecoderContext.builder().build());
485
reader.readEndDocument();
486
reader.close();
487
```
488
489
### Custom POJO Codec
490
491
```java
492
import org.bson.codecs.pojo.annotations.*;
493
494
public class Person {
495
@BsonId
496
private ObjectId id;
497
498
@BsonProperty("full_name")
499
private String name;
500
501
private int age;
502
503
@BsonIgnore
504
private String password;
505
506
@BsonCreator
507
public Person(@BsonProperty("full_name") String name, @BsonProperty("age") int age) {
508
this.name = name;
509
this.age = age;
510
}
511
512
// getters and setters
513
public String getName() { return name; }
514
public void setName(String name) { this.name = name; }
515
public int getAge() { return age; }
516
public void setAge(int age) { this.age = age; }
517
}
518
519
// Register the POJO codec
520
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
521
CodecRegistries.getDefaultCodecRegistry(),
522
CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
523
);
524
525
// Use the POJO codec
526
Codec<Person> personCodec = pojoCodecRegistry.get(Person.class);
527
```
528
529
### Creating a Custom Registry
530
531
```java
532
import org.bson.codecs.*;
533
import org.bson.codecs.configuration.*;
534
535
// Create a custom codec registry
536
CodecRegistry customRegistry = CodecRegistries.fromRegistries(
537
// Default codecs
538
CodecRegistries.getDefaultCodecRegistry(),
539
540
// Custom codecs
541
CodecRegistries.fromCodecs(
542
new UuidCodec(UuidRepresentation.STANDARD)
543
),
544
545
// POJO support
546
CodecRegistries.fromProviders(
547
PojoCodecProvider.builder()
548
.register(Person.class)
549
.conventions(Arrays.asList(
550
Conventions.ANNOTATION_CONVENTION,
551
Conventions.CLASS_AND_PROPERTY_CONVENTION
552
))
553
.build()
554
)
555
);
556
```
557
558
### Working with Polymorphic Types
559
560
```java
561
@BsonDiscriminator(key = "type", value = "vehicle")
562
public abstract class Vehicle {
563
@BsonId
564
private ObjectId id;
565
private String brand;
566
567
// constructors, getters, setters
568
}
569
570
@BsonDiscriminator(value = "car")
571
public class Car extends Vehicle {
572
private int doors;
573
// constructors, getters, setters
574
}
575
576
@BsonDiscriminator(value = "truck")
577
public class Truck extends Vehicle {
578
private double cargoCapacity;
579
// constructors, getters, setters
580
}
581
582
// Register all types in the hierarchy
583
CodecRegistry registry = CodecRegistries.fromRegistries(
584
CodecRegistries.getDefaultCodecRegistry(),
585
CodecRegistries.fromProviders(
586
PojoCodecProvider.builder()
587
.register(Vehicle.class, Car.class, Truck.class)
588
.build()
589
)
590
);
591
```