1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
+++
date = "2015-03-19T14:27:51-04:00"
title = "Readers and Writers"
[menu.main]
parent = "BSON"
weight = 30
pre = "<i class='fa'></i>"
+++
## BsonWriter and BsonReader
The various implementations of the `Bson` interface discussed in the previous section all represent BSON documents using an underlying
Java `Map` instance. However, they are not directly responsible for reading and writing their representations from and to BSON. Instead,
this process is delegated to [`BsonWriter`]({{< apiref "org/bson/BsonWriter" >}}) and
[`BsonReader`]({{< apiref "org/bson/BsonReader" >}}), abstract classes that expose methods for iterative, stream-based processing of
BSON documents.
### BsonWriter
The `BsonWriter` class exposes methods for writing a BSON document. Consider the task of writing the document
```javascript
{
"a" : "MongoDB",
"b" : [
{ "c": 1 }
]
}
```
The following code will stream a document of this structure to a `BsonWriter`:
```java
BsonWriter writer = ... // Construct a BsonWriter
writer.writeStartDocument();
writer.writeName("a");
writer.writeString("MongoDB");
writer.writeName("b");
writer.writeStartArray();
writer.writeStartDocument();
writer.writeName("c");
writer.writeInt32(1);
writer.writeEndDocument();
writer.writeEndArray();
writer.writeEndDocument();
```
The indentation is not necessary: it's just to clarify that the stream of events written to the `BsonWriter`, although written
iteratively, have an implicit hierarchical structure. The BsonWriter validates that the events create only properly structured BSON
documents. Otherwise, it throws a `BsonSerializationException`.
The two most important classes to extend `BsonWriter` are [`BsonBinaryWriter`]({{< apiref "org/bson/BsonBinaryWriter" >}}) and
[`JsonWriter`]({{< apiref "org/bson/json/JsonWriter" >}}). `BsonBinaryWriter` writes the BSON
document as a stream of bytes in accordance with the [BSON](http://www.bsonspec.org) specification, while `JsonWriter` writes the BSON
document as a stream of characters in accordance with
[MongoDB Extended JSON](https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
### BsonReader
The `BsonReader` class exposes methods for reading a BSON document. Consider the task of reading the document written above with a
`BsonReader`:
```java
BsonReader reader = ... // Construct a BsonReader
reader.readStartDocument();
reader.readName(); // read the name "a"
reader.readString(); // read string "MongoDB"
reader.readName(); // read the name "b"
reader.readStartArray();
reader.readStartDocument();
reader.readName(); // read the name "c"
reader.readInt32(); // read the integer 1
reader.readEndDocument();
reader.readEndArray();
reader.readEndDocument();
```
As with the writer example, the indentation is not necessary: it's just to clarify that the stream of events read from the `BsonWriter`,
although written iteratively, have an implicit hierarchical structure. The BsonReader will throw a `BsonSerializationException` if the
events read do not match the structure of the document that is being read from.
In most situations an application will not know the exact structure of the document being read. For that reason, `BsonReader`
exposes a few methods that allow an application to peak ahead so that it can figure out what method to call next. Consider a situation
where an application must read a BSON document with an unknown structure:
```java
reader.readStartDocument();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
String fieldName = reader.readName();
switch (reader.getCurrentBsonType()) {
case INT32:
int intValue = reader.readInt32();
break;
case INT64:
long longValue = reader.readInt64();
break;
// ... handle each supported field type
}
}
reader.readEndDocument();
```
In this example, the application iterates through the fields of the document until it reaches `END_OF_DOCUMENT`. For each field, it
reads the name and then the value based on the `BsonType` of the field.
A similar pattern can be used to read a BSON array:
```java
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
switch (reader.getCurrentBsonType()) {
case INT32:
int intValue = reader.readInt32();
break;
case INT64:
long longValue = reader.readInt64();
break;
// ... handle each supported field type
}
}
reader.readEndArray();
```
The only significant difference between reading an array and reading a document is that, since the elements of an array do not have names,
there is no field name to read, only a series of values.
The two most important classes to extend `BsonReader` are [`BsonBinaryReader`]({{< apiref "org/bson/BsonBinaryReader" >}}) and
[`JsonReader`]({{< apiref "org/bson/json/JsonReader" >}}). `BsonBinaryReader` reads the BSON
document as a stream of bytes in accordance with the [BSON](http://www.bsonspec.org) specification, while `JsonReader` reads the BSON
document as a stream of characters in accordance with
[MongoDB Extended JSON](https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
|