Skip to content

Commit beba6e9

Browse files
authored
DOCSP-38478: bson ext json (#9)
* DOCSP-38478: bson ext json * links
1 parent 3263b08 commit beba6e9

File tree

2 files changed

+151
-3
lines changed

2 files changed

+151
-3
lines changed

source/bson.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ BSON Implementation
1515

1616
/bson/documents/
1717
/bson/macros/
18+
/bson/extended-json/
1819

1920
The BSON library comprehensively supports `BSON
2021
<https://bsonspec.org/>`__, the data storage and network transfer format
@@ -31,13 +32,11 @@ implementation.
3132
The following sections describe aspects of the driver's BSON
3233
implementation:
3334

34-
.. TODO add links
35-
3635
- :ref:`scala-documents`: describes the driver’s support for BSON document
3736
representations
3837
- :ref:`scala-macros`: describes the case classes you can use to
3938
represent documents in a collection
40-
- Extended JSON: describes the driver’s support for MongoDB Extended
39+
- :ref:`scala-ejson`: describes the driver’s support for MongoDB Extended
4140
JSON
4241

4342
For advanced usage you might need to use ``org.bson`` directly. See the

source/bson/extended-json.txt

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
.. _scala-ejson:
2+
3+
=============
4+
Extended JSON
5+
=============
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: documents, storage, codec, registry
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
The {+driver-short+} supports reading and writing of BSON documents
24+
represented as MongoDB Extended JSON. Both of the following variants are supported:
25+
26+
- Strict Mode: representations of BSON types that conform to the `JSON
27+
RFC <https://www.json.org/json-en.html>`__. This is the format that
28+
:dbtools:`mongoexport </mongoexport/>` produces and
29+
:dbtools:`mongoimport </mongoimport/>` consumes.
30+
31+
- Shell Mode: a superset of JSON that the :mongosh:`MongoDB shell </>` can parse.
32+
33+
Furthermore, the ``Document`` type provides two sets of convenience
34+
methods for this purpose:
35+
36+
- ``Document.toJson()``: a set of overloaded methods that convert a
37+
``Document`` instance to a JSON string
38+
- ``Document(<json>)``: a set of overloaded static factory methods that
39+
convert a JSON string to a ``Document`` instance
40+
41+
Writing JSON
42+
------------
43+
44+
Consider the task of implementing a ``mongoexport``-like tool by using
45+
the driver:
46+
47+
.. code-block:: scala
48+
49+
val fileName = // initialize to the path of the file to write to
50+
val collection = // initialize the collection from which you want to query
51+
52+
val writer: PrintWriter = new PrintWriter(fileName)
53+
collection.find().subscribe(
54+
(doc: Document) => output.write(s"${doc.toJson}\r\n"),
55+
(t: Throwable) => // handle failure,
56+
() => output.close())
57+
58+
The ``Document.toJson()`` method constructs an instance of a ``JsonWriter`` with
59+
its default settings, which writes in strict mode with no new lines
60+
or indentation.
61+
62+
You can override this default behavior by using one of the overloads of
63+
``toJson()``. As an example, consider the task of writing a JSON string
64+
that can be copied and pasted into the MongoDB shell:
65+
66+
.. code-block:: scala
67+
68+
import java.text.SimpleDateFormat
69+
70+
val fmt = new SimpleDateFormat("dd/MM/yy")
71+
val first = fmt.parse("01/01/2014")
72+
val second = fmt.parse("01/01/2015")
73+
val doc = Document("startDate" -> Document("$gt" -> first, "$lt" -> second))
74+
println(doc.toJson(new JsonWriterSettings(JsonMode.SHELL)))
75+
76+
This code snippet will print out MongoDB shell-compatible JSON, which
77+
can then be pasted into the shell:
78+
79+
.. code-block:: shell
80+
81+
{ "startDate" : { "$gt" : ISODate("2014-01-01T05:00:00.000Z"), "$lt" : ISODate("2015-01-01T05:00:00.000Z") } }
82+
83+
Reading JSON
84+
------------
85+
86+
Consider the task of implementing a ``mongoimport``-like tool by using
87+
driver:
88+
89+
.. code-block:: scala
90+
91+
import scala.io.Source
92+
val fileName = // initialize to the path of the file to read from
93+
val collection = // initialize the collection from which you want to import to
94+
95+
try {
96+
for (json <- Source.fromFile(fileName).getLines()) {
97+
collection.insertOne(Document(json)).head()
98+
}
99+
} catch {
100+
case ex: Exception => println("Bummer, an exception happened.")
101+
}
102+
103+
The ``Document(<json>)`` companion helper method constructs an instance of a
104+
``JsonReader`` with the given string and returns an instance of an
105+
equivalent ``Document`` instance. ``JsonReader`` automatically detects the JSON
106+
flavor in the string, so you do not need to specify it.
107+
108+
Reading and Writing JSON Directly
109+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110+
111+
If you do not need a document and only want to deal with JSON, you can
112+
use a ``JsonObject`` to read and write JSON directly. ``JsonObject`` is a
113+
wrapper class that takes in a ``String`` in the constructor and returns the
114+
``String`` in the ``getJson()`` method. Reading and writing JSON directly is
115+
more efficient than constructing a ``Document`` first and then calling
116+
``toJson()``, and it is also more efficient than calling
117+
``Document#parse()``.
118+
119+
The codec responsible for reading/writing JSON, ``JsonObjectCodec``, is part of
120+
the default registry, so doing this is very simple and demonstrated by
121+
the following example:
122+
123+
.. code-block:: scala
124+
125+
val database: MongoDatabase = mongoClient.getDatabase("mydb")
126+
val collection: MongoCollection[JsonObject] = database.getCollection("test")
127+
collection.insertOne(new JsonObject("{hello: 1}")).printResults()
128+
val jsonObject: SingleObservable[JsonObject] = collection.find.first()
129+
130+
Reading and Writing JSON with CustomSettings
131+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132+
133+
You can also provide custom ``JsonWriterSettings`` to the ``JsonObjectCodec``,
134+
by constructing the codec yourself and then creating a registry:
135+
136+
.. code-block:: scala
137+
138+
val codecRegistry =
139+
fromRegistries(
140+
fromCodecs(new JsonObjectCodec(JsonWriterSettings
141+
.builder()
142+
.outputMode(JsonMode.EXTENDED)
143+
.build())),
144+
DEFAULT_CODEC_REGISTRY
145+
)
146+
val database: MongoDatabase = mongoClient.getDatabase("mydb").withCodecRegistry(codecRegistry)
147+
val collection: MongoCollection[JsonObject] = database.getCollection("test")
148+
collection.insertOne(new JsonObject("{hello: 1}")).printResults()
149+
val jsonObject: SingleObservable[JsonObject] = collection.find.first()

0 commit comments

Comments
 (0)