Skip to content

Commit ad8e0d0

Browse files
author
Chris Cho
authored
Merge pull request #37 from ccho-mongodb/DOCSP-12157-fundamentals-json
DOCSP-12157: Fundamentals Extended JSON
2 parents 0755450 + 47fea5d commit ad8e0d0

File tree

3 files changed

+306
-45
lines changed

3 files changed

+306
-45
lines changed

source/fundamentals/data-formats.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Data Formats
77
.. toctree::
88

99
/fundamentals/data-formats/document-data-format-bson
10-
/fundamentals/data-formats/document-data-format-json
10+
/fundamentals/data-formats/document-data-format-extended-json
1111
/fundamentals/data-formats/documents
1212
/fundamentals/data-formats/document-data-format-pojo
1313
/fundamentals/data-formats/pojo-customization
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
===================================
2+
Document Data Format: Extended JSON
3+
===================================
4+
5+
.. default-domain:: mongodb
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
14+
Overview
15+
--------
16+
17+
JSON is a data format that represents the values of objects, arrays, numbers,
18+
strings, booleans, and nulls. The **Extended JSON** format defines a reserved
19+
set of keys prefixed with "``$``" to represent field type information that
20+
directly corresponds to each type in BSON, the format that MongoDB uses to
21+
store data.
22+
23+
This guide explains the following topics:
24+
25+
- the different MongoDB Extended JSON formats
26+
- how to use the BSON library to convert between Extended JSON and Java objects
27+
- how to create a custom conversion of BSON types
28+
29+
For more information on the difference between these formats, see our
30+
`article on JSON and BSON <https://www.mongodb.com/json-and-bson>`__.
31+
32+
Extended JSON Formats
33+
---------------------
34+
35+
MongoDB Extended JSON features different string formats to represent BSON data.
36+
Each of the different formats conform to the `JSON RFC <https://tools.ietf.org/html/rfc7159>`__
37+
and meet specific use cases. The **extended** format, also known as the
38+
**canonical** format, features specific representations for every BSON type
39+
for bidirectional conversion without loss of information. The **relaxed**
40+
format is more concise and closer to ordinary JSON, but does not represent
41+
all the type information such as specific byte size of number fields.
42+
43+
See the table below to see a description of each format:
44+
45+
.. list-table::
46+
:header-rows: 1
47+
:stub-columns: 1
48+
:widths: 10 40
49+
50+
* - Name
51+
- Description
52+
53+
* - **Extended**
54+
- | Also known as the *canonical* format, this JSON representation avoids loss of BSON type information.
55+
| This format prioritizes type preservation at the loss of human-readability and interoperability with older formats.
56+
|
57+
| For more information on this format, see the server manual page on :manual:`MongoDB Extended JSON </reference/mongodb-extended-json/>`.
58+
59+
* - **Relaxed**
60+
- | JSON representation that describes BSON documents with some type information loss.
61+
| This format prioritizes human-readability and interoperability at the loss of certain type information.
62+
|
63+
| For more information on this format, see the server manual page on :manual:`MongoDB Extended JSON </reference/mongodb-extended-json/>`.
64+
65+
* - **Shell**
66+
- | JSON representation that matches the syntax used in the MongoDB shell.
67+
| This format prioritizes for compatibility with the MongoDB shell which often uses JavaScript functions to represent types.
68+
|
69+
| For more information on this format, see the server manual page on :manual:`Data Types in the mongo shell </core/shell-types/>`.
70+
71+
.. _extended_json_example_section:
72+
73+
For more detailed information on these formats, see the
74+
`Extended JSON specification <https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>`__.
75+
76+
Extended JSON Examples
77+
~~~~~~~~~~~~~~~~~~~~~~
78+
79+
The following examples show a document containing an ObjectId, date, and long
80+
number field represented in each Extended JSON format. Click the tab that
81+
corresponds to the format of the example you want to see:
82+
83+
.. tabs::
84+
85+
.. tab:: Extended
86+
:tabid: extended-format
87+
88+
.. code-block:: json
89+
90+
{
91+
"_id": { "$oid": "573a1391f29313caabcd9637" },
92+
"createdAt": { "$date": { "$numberLong": "1601499609" }},
93+
"numViews": { "$numberLong": "36520312" }
94+
}
95+
96+
.. tab:: Relaxed
97+
:tabid: relaxed-format
98+
99+
.. code-block:: json
100+
101+
{
102+
"_id": { "$oid": "573a1391f29313caabcd9637" },
103+
"createdAt": { "$date": "2020-09-30T18:22:51.648Z" },
104+
"numViews": 36520312
105+
}
106+
107+
.. tab:: Shell
108+
:tabid: shell-format
109+
110+
.. code-block:: json
111+
112+
{
113+
"_id:": ObjectId("573a1391f29313caabcd9637"),
114+
"createdAt": ISODate("2020-09-30T18:22:51.648Z"),
115+
"numViews": NumberLong("36520312")
116+
}
117+
118+
119+
Read Extended JSON
120+
------------------
121+
122+
Using the Document Classes
123+
~~~~~~~~~~~~~~~~~~~~~~~~~~
124+
125+
You can read an Extended JSON string into Java document objects by calling
126+
the ``parse()`` static method from either the ``Document`` or ``BsonDocument``
127+
class, depending on which object type you need. This method parses the Extended
128+
JSON string in any of the formats and returns an instance of that class
129+
containing the data.
130+
131+
The following example shows how you can use the ``Document`` class to read
132+
an example Extended JSON string into a ``Document`` object using the
133+
``parse()`` method:
134+
135+
.. code-block:: java
136+
137+
String ejsonStr = "{ \"_id\": { \"$oid\": \"507f1f77bcf86cd799439011\"}," +
138+
"\"myNumber\": {\"$numberLong\": \"4794261\" }}}";
139+
140+
Document doc = Document.parse(ejsonStr);
141+
System.out.println(doc);
142+
143+
The output of the code above resembles the following:
144+
145+
.. code-block:: none
146+
:copyable: False
147+
148+
Document{{_id=507f1f77bcf86cd799439011, myNumber=4794261}}
149+
150+
For more information on the driver document classes, see our Fundamentals page
151+
on :doc:`Documents </fundamentals/data-formats/documents>`.
152+
153+
Using the BSON Library
154+
~~~~~~~~~~~~~~~~~~~~~~
155+
156+
You can also read an Extended JSON string into Java objects without using
157+
the MongoDB driver's document classes by using the
158+
:java-docs:`JsonReader </apidocs/bson/org/bson/json/JsonReader.html>` class.
159+
This class contains methods to sequentially parse the fields and values
160+
in any format of the Extended JSON string, and returns them as Java objects.
161+
MongoDB driver's document classes also use this class to parse Extended JSON.
162+
163+
The following code example shows how you can use ``JsonReader`` to convert
164+
an Extended JSON string into Java objects:
165+
166+
.. code-block:: java
167+
168+
String ejsonStr = "{ \"_id\": { \"$oid\": \"507f1f77bcf86cd799439011\"}," +
169+
"\"myNumber\": {\"$numberLong\": \"4794261\" }}}";
170+
171+
JsonReader jsonReader = new JsonReader(ejsonStr);
172+
173+
jsonReader.readStartDocument();
174+
175+
jsonReader.readName("_id");
176+
ObjectId id = jsonReader.readObjectId();
177+
jsonReader.readName("myNumber");
178+
Long myNumber = jsonReader.readInt64();
179+
180+
jsonReader.readEndDocument();
181+
182+
System.out.println(id + " is type: " + id.getClass().getName());
183+
System.out.println(myNumber + " is type: " + myNumber.getClass().getName());
184+
185+
jsonReader.close();
186+
187+
The output of this code example resembles the following:
188+
189+
.. code-block:: none
190+
:copyable: False
191+
192+
507f1f77bcf86cd799439011 is type: org.bson.types.ObjectId
193+
4794261 is type: java.lang.Long
194+
195+
196+
For additional information on the classes and methods mentioned on this
197+
section, see the following API documentation:
198+
199+
Write Extended JSON
200+
-------------------
201+
202+
Using the Document Classes
203+
~~~~~~~~~~~~~~~~~~~~~~~~~~
204+
205+
You can write an Extended JSON string from an instance of ``Document`` or
206+
``BsonDocument`` by calling the ``toJson()`` method, optionally passing it an
207+
instance of ``JsonWriterSettings`` to specify the Extended JSON format.
208+
209+
In this example, we output the Extended JSON in the "Relaxed" format.
210+
211+
.. code-block:: java
212+
213+
Document myDoc = new Document();
214+
myDoc.append("_id", new ObjectId("507f1f77bcf86cd799439012")).append("myNumber", 11223344);
215+
216+
JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build();
217+
System.out.println(doc.toJson(settings));
218+
219+
The output of this code example resembles the following:
220+
221+
.. code-block:: none
222+
:copyable: false
223+
224+
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": 11223344}
225+
226+
Using the BSON Library
227+
~~~~~~~~~~~~~~~~~~~~~~
228+
229+
You can also output an Extended JSON string from data in Java objects using
230+
the BSON library with the :java-docs:`JsonWriter </apidocs/bson/org/bson/json/JsonWriter.html>`
231+
class. To construct an instance of ``JsonWriter``, pass a subclass of a Java
232+
``Writer`` to specify how you want to output the Extended JSON. You can
233+
optionally pass a :java-docs:`JsonWriterSettings </apidocs/bson/org/bson/json/JsonWriterSettings.html>`
234+
instance to specify options such as the Extended JSON format. By default, the
235+
``JsonWriter`` uses the "Relaxed" Extended JSON format. MongoDB driver's
236+
document classes also use this class to convert BSON to Extended JSON.
237+
238+
The following code example shows how you can use ``JsonWriter`` to create an
239+
Extended JSON string and output it to ``System.out``. We specify the format
240+
by passing the :java-docs:`outputMode() </apidocs/bson/org/bson/json/JsonWriterSettings.Builder.html#outputMode(org.bson.json.JsonMode)>`
241+
builder method the ``JsonMode.EXTENDED`` constant:
242+
243+
.. code-block:: java
244+
245+
JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build();
246+
247+
try (JsonWriter jsonWriter = new JsonWriter(new BufferedWriter(new OutputStreamWriter(System.out)), settings)) {
248+
jsonWriter.writeStartDocument();
249+
jsonWriter.writeObjectId("_id", new ObjectId("507f1f77bcf86cd799439012"));
250+
jsonWriter.writeInt64("myNumber", 11223344);
251+
jsonWriter.writeEndDocument();
252+
jsonWriter.flush();
253+
}
254+
255+
The output of this code example resembles the following:
256+
257+
.. code-block:: none
258+
:copyable: false
259+
260+
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": {"$numberLong": "11223344"}}
261+
262+
263+
Custom BSON Type Conversion
264+
---------------------------
265+
266+
In addition to specifying the ``outputMode()`` to format the JSON output, you
267+
can further customize the output by adding converters to your
268+
``JsonWriterSettings.Builder``. These converter methods detect the Java types
269+
and execute the logic defined by the :java-docs:`Converter </apidocs/bson/org/bson/json/Converter.html>`
270+
passed to them. For a full list of converter methods, see the
271+
:java-docs:`API documentation </apidocs/bson/org/bson/json/JsonWriterSettings.Builder.html>`.
272+
273+
The following sample code shows how to append converters, defined as lambda
274+
expressions, to simplify the "Relaxed" JSON output.
275+
276+
.. code-block:: java
277+
278+
JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED)
279+
.objectIdConverter((value, writer) -> writer.writeString(value.toHexString()))
280+
.dateTimeConverter(
281+
(value, writer) -> {
282+
ZonedDateTime zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC);
283+
writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime));
284+
})
285+
.build();
286+
287+
Document doc = new Document()
288+
.append("_id", new ObjectId("507f1f77bcf86cd799439012"))
289+
.append("createdAt", Date.from(Instant.ofEpochMilli(1601499609000L)))
290+
.append("myNumber", 4794261);
291+
292+
System.out.println(doc.toJson(settings)));
293+
294+
The output of this code should resemble the following:
295+
296+
.. code-block:: json
297+
298+
{"_id": "507f1f77bcf86cd799439012", "createdAt": "2020-09-30T21:00:09Z", "myNumber": 4794261}
299+
300+
Without specifying the converters, the "Relaxed" JSON output resembles the
301+
following:
302+
303+
.. code-block:: json
304+
305+
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "createdAt": {"$date": "2020-09-30T21:00:09Z"}, "myNumber": 4794261}

source/fundamentals/data-formats/document-data-format-json.txt

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)