Skip to content

Commit 1c1af83

Browse files
DOCSP-46694 - Extended JSON (#169) (#172)
Co-authored-by: Jordan Smith <[email protected]> (cherry picked from commit fe2c41a) Co-authored-by: Mike Woofter <[email protected]>
1 parent 05a8ed1 commit 1c1af83

File tree

2 files changed

+284
-0
lines changed

2 files changed

+284
-0
lines changed

source/data-formats.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Specialized Data Formats
2222
:maxdepth: 1
2323

2424
BSON </data-formats/bson>
25+
Extended JSON </data-formats/extended-json>
2526
Custom Types </data-formats/custom-types>
2627
Dates & Times </data-formats/dates-and-times>
2728
UUIDs </data-formats/uuid>
@@ -35,6 +36,7 @@ application. To learn how to work with these data formats, see the following
3536
sections:
3637

3738
- Learn how to work with BSON documents in the :ref:`pymongo-bson` guide.
39+
- Learn how to translate BSON to Extended JSON in the :ref:`pymongo-extended-json` guide.
3840
- Learn how to encode and decode custom types in the :ref:`pymongo-custom-types` guide.
3941
- Learn how to work with Python ``datetime`` objects in {+driver-short+} in the
4042
:ref:`pymongo-dates-times` guide.

source/data-formats/extended-json.txt

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
.. _pymongo-extended-json:
2+
3+
=============
4+
Extended JSON
5+
=============
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: code examples, bson, relaxed, canonical, legacy
19+
20+
Overview
21+
--------
22+
23+
JSON is a data format that represents the values of objects, arrays, numbers,
24+
strings, booleans, and nulls. The **Extended JSON** format defines a reserved
25+
set of keys prefixed with "``$``" to represent field type information that
26+
directly corresponds to each type in BSON, the format that MongoDB uses to
27+
store data.
28+
29+
Extended JSON Formats
30+
---------------------
31+
32+
MongoDB Extended JSON features different string formats to represent BSON data.
33+
Each of the different formats conform to the JSON RFC
34+
and meet specific use cases. The **extended** format, also known as the
35+
**canonical** format, features specific representations for every BSON type
36+
for bidirectional conversion without loss of information. The **Relaxed mode**
37+
format is more concise and closer to ordinary JSON, but does not represent
38+
all the type information such as the specific byte size of number fields.
39+
40+
See the following table to see a description of each format:
41+
42+
.. list-table::
43+
:header-rows: 1
44+
:stub-columns: 1
45+
:widths: 10 40
46+
47+
* - Name
48+
- Description
49+
50+
* - **Extended**
51+
- | Also known as the *canonical* format, this JSON representation avoids loss of
52+
BSON type information.
53+
| This format prioritizes type preservation at the loss of human-readability and
54+
interoperability with older formats.
55+
56+
* - **Relaxed Mode**
57+
- | JSON representation that describes BSON documents with some type information loss.
58+
| This format prioritizes human-readability and interoperability at the loss of
59+
certain type information.
60+
61+
* - **Shell**
62+
- | JSON representation that matches the syntax used in the MongoDB shell.
63+
| This format prioritizes compatibility with the MongoDB shell, which often uses
64+
JavaScript functions to represent types.
65+
66+
* - **Strict**
67+
- | *Deprecated.* This representation is the legacy format that fully conforms to
68+
the `JSON RFC <http://www.json.org/>`__ which allows any JSON parser to read the type information.
69+
70+
.. _extended_json_example_section:
71+
72+
.. note::
73+
74+
The driver parses the ``$uuid`` Extended JSON type from a string to a
75+
``BsonBinary`` object of binary subtype 4. For more information about ``$uuid`` field
76+
parsing, see the
77+
:spec:`special rules for parsing $uuid fields </extended-json.rst#special-rules-for-parsing-uuid-fields>`
78+
section in the extended JSON specification.
79+
80+
To learn more about JSON, BSON, and Extended JSON, see
81+
`our article about JSON and BSON <https://www.mongodb.com/resources/basics/json-and-bson>`__
82+
and :manual:`Extended JSON </reference/mongodb-extended-json/>` in the {+mdb-server+} manual.
83+
84+
Extended JSON Examples
85+
~~~~~~~~~~~~~~~~~~~~~~
86+
87+
The following examples show a document containing an ObjectId, date, and long
88+
number field represented in each Extended JSON format. Click the tab that
89+
corresponds to the format of the example you want to see:
90+
91+
.. tabs::
92+
93+
.. tab:: Extended
94+
:tabid: extended-format
95+
96+
.. code-block:: json
97+
98+
{
99+
"_id": { "$oid": "573a1391f29313caabcd9637" },
100+
"createdAt": { "$date": { "$numberLong": "1601499609" }},
101+
"numViews": { "$numberLong": "36520312" }
102+
}
103+
104+
.. tab:: Relaxed Mode
105+
:tabid: relaxed-mode-format
106+
107+
.. code-block:: json
108+
109+
{
110+
"_id": { "$oid": "573a1391f29313caabcd9637" },
111+
"createdAt": { "$date": "2020-09-30T18:22:51.648Z" },
112+
"numViews": 36520312
113+
}
114+
115+
.. tab:: Shell
116+
:tabid: shell-format
117+
118+
.. code-block:: json
119+
120+
{
121+
"_id": ObjectId("573a1391f29313caabcd9637"),
122+
"createdAt": ISODate("2020-09-30T18:22:51.648Z"),
123+
"numViews": NumberLong("36520312")
124+
}
125+
126+
.. tab:: Strict
127+
:tabid: strict-format
128+
129+
.. code-block:: json
130+
131+
{
132+
"_id": { "$oid": "573a1391f29313caabcd9637" },
133+
"createdAt": { "$date": 1601499609 },
134+
"numViews": { "$numberLong": "36520312" }
135+
}
136+
137+
Read Extended JSON
138+
------------------
139+
140+
You can read an Extended JSON string into a Python object by calling
141+
the ``bson.json_util.loads()`` method. This method parses an Extended
142+
JSON string and returns a Python list containing the data.
143+
144+
The following example shows how you can read an Extended JSON string into a
145+
list of dictionaries by using the ``loads()`` method:
146+
147+
.. io-code-block::
148+
149+
.. input::
150+
:language: python
151+
152+
from bson.json_util import loads
153+
154+
ejson_str = '''[
155+
{"foo": [1, 2]},
156+
{"bar": {"hello": "world"}},
157+
{"code": {
158+
"$scope": {},
159+
"$code": "function x() { return 1; }"
160+
}},
161+
{"bin": {
162+
"$type": "80",
163+
"$binary": "AQIDBA=="
164+
}}
165+
]'''
166+
167+
doc = loads(ejson_str)
168+
print(doc)
169+
170+
.. output::
171+
:language: none
172+
:visible: false
173+
174+
[
175+
{'foo': [1, 2]},
176+
{'bar': {'hello': 'world'}},
177+
{'code': Code('function x() { return 1; }', {})},
178+
{'bin': Binary(b'\x01\x02\x03\x04', 128)}
179+
]
180+
181+
Write Extended JSON
182+
-------------------
183+
184+
You can write an Extended JSON string from a list of dictionaries
185+
by calling the ``bson.json_util.dumps()`` method.
186+
The following example outputs an Extended JSON string in the Relaxed format:
187+
188+
.. io-code-block::
189+
190+
.. input::
191+
:language: python
192+
193+
from bson import Code, Binary
194+
from bson.json_util import dumps
195+
196+
doc = [
197+
{'foo': [1, 2]},
198+
{'bar': {'hello': 'world'}},
199+
{'code': Code('function x() { return 1; }', {})},
200+
{'bin': Binary(b'\x01\x02\x03\x04', 128)}
201+
]
202+
203+
ejson_str = dumps(doc)
204+
print(ejson_str)
205+
206+
.. output::
207+
:language: none
208+
:visible: false
209+
210+
'''[
211+
{"foo": [1, 2]},
212+
{"bar": {"hello": "world"}},
213+
{"code": {
214+
"$code": "function x() { return 1; }",
215+
"$scope": {}
216+
}},
217+
{"bin": {
218+
"$binary": {
219+
"base64": "AQIDBA==",
220+
"subType": "80"
221+
}}}
222+
]'''
223+
224+
By default, the ``dumps()`` method returns the Extended JSON string in the Relaxed
225+
format. To specify a different format, pass one of the following values for the
226+
``json_options`` parameter:
227+
228+
- ``CANONICAL_JSON_OPTIONS``: Returns the Extended JSON string in Canonical format.
229+
- ``LEGACY_JSON_OPTIONS``: Returns the Extended JSON string in Legacy format.
230+
We recommend using Relaxed or Canonical format instead.
231+
232+
The following example shows how to output Extended JSON in the Canonical format:
233+
234+
.. io-code-block::
235+
236+
.. input::
237+
:language: python
238+
239+
from bson import Code, Binary
240+
from bson.json_util import dumps, CANONICAL_JSON_OPTIONS
241+
242+
doc = [
243+
{'foo': [1, 2]},
244+
{'bar': {'hello': 'world'}},
245+
{'code': Code('function x() { return 1; }', {})},
246+
{'bin': Binary(b'\x01\x02\x03\x04', 128)}
247+
]
248+
249+
ejson_str = dumps(doc, json_options=CANONICAL_JSON_OPTIONS)
250+
print(ejson_str)
251+
252+
.. output::
253+
:language: none
254+
:visible: false
255+
256+
'''[
257+
{"foo": [
258+
{"$numberInt": "1"},
259+
{"$numberInt": "2"}
260+
]},
261+
{"bar": {"hello": "world"}},
262+
{"code": {
263+
"$code": "function x() { return 1; }",
264+
"$scope": {}
265+
}},
266+
{"bin": {
267+
"$binary": {
268+
"base64": "AQIDBA==",
269+
"subType": "80"
270+
}}}
271+
]'''
272+
273+
Additional Information
274+
----------------------
275+
276+
For more information about the methods and types in ``bson.json_util``, see the following
277+
API documentation:
278+
279+
- `loads() <{+api-root+}bson/json_util.html#bson.json_util.loads>`__
280+
- `dumps() <{+api-root+}bson/json_util.html#bson.json_util.dumps>`__
281+
- `CANONICAL_JSON_OPTIONS <{+api-root+}bson/json_util.html#bson.json_util.CANONICAL_JSON_OPTIONS>`__
282+
- `LEGACY_JSON_OPTIONS <{+api-root+}bson/json_util.html#bson.json_util.LEGACY_JSON_OPTIONS>`__

0 commit comments

Comments
 (0)