Skip to content

DOCSP-48390 Document Data Formats: EJSON #1069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Apr 14, 2025
1 change: 1 addition & 0 deletions source/data-formats.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Specialized Data Formats
:maxdepth: 1

BSON </data-formats/bson>
Extended JSON <data-formats/extended-json>
Time Series Data </data-formats/time-series>

Overview
Expand Down
21 changes: 15 additions & 6 deletions source/data-formats/bson.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.. _node-bson-control:
.. _node-bson:

==============
Work with BSON
==============
===================
Work with BSON Data
===================

.. default-domain:: mongodb

Expand Down Expand Up @@ -40,6 +40,16 @@ The code samples in this guide use the following BSON document as an example:
"name" : "Mongo's Pizza"
}

.. note:: Use the {+driver-short+}'s BSON package

We recommend that you use the BSON package that is bundled with the driver to avoid
compatibility issues with other BSON packages. You can import the {+driver-short+}'s
BSON package with the following import statement:

.. code-block:: js

import { BSON } from 'mongodb';

Create a BSON Document
----------------------

Expand Down Expand Up @@ -91,7 +101,7 @@ The following example writes the sample BSON document to ``file.bson``:
.. code-block:: javascript

import fs from 'fs/promises'; // Import the file system module
import { BSON } from 'bson'; // Import the BSON package
import { BSON } from 'mongodb'; // Import the BSON package

// Create a BSON object
const bsonData = BSON.serialize(result);
Expand All @@ -115,7 +125,7 @@ The following example reads the sample BSON document from ``file.bson``:
:language: javascript

import fs from 'fs/promises'; // Import the file system module
import { BSON } from 'bson'; // Import the BSON package
import { BSON } from 'mongodb'; // Import the BSON package

// Read the BSON data from a file
const data = await fs.readFile('file.bson');
Expand All @@ -138,4 +148,3 @@ API Documentation

To learn more about any of the methods or types discussed in this
guide, see the `BSON <{+api+}/modules/BSON.html>`__ API documentation.

219 changes: 219 additions & 0 deletions source/data-formats/extended-json.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
.. _node-extended-json:

============================
Work with Extended JSON Data
============================

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: code examples, bson, relaxed, canonical, legacy

Overview
--------

JSON is a data format that represents the values of objects, arrays, numbers,
strings, booleans, and nulls. The **Extended JSON** format defines a reserved
set of keys prefixed with "``$``" to represent field type information that
directly corresponds to each type in BSON, the format that MongoDB uses to
store data.

Extended JSON Formats
---------------------

MongoDB Extended JSON features different string formats to represent BSON data.
Each of the different formats conform to the JSON RFC
and meet specific use cases. The **Extended** format, also known as the
**Canonical** format, features specific representations for every BSON type
for bidirectional conversion without loss of information. The **Relaxed Mode**
Comment on lines +34 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] Do you know if the different format names are meant to be capitalized? I think it makes sense to do so, but I've seen a mix in different docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be capitalized in the Server Docs, so I tried to be consistent: https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/

format is more concise and closer to ordinary JSON, but does not represent
all the type information such as the specific bit width of numeric fields.

See the following table to see a description of each format:

.. list-table::
:header-rows: 1
:stub-columns: 1
:widths: 10 40

* - Name
- Description

* - **Extended**
- | Also known as the *Canonical* format, this JSON representation avoids loss of
BSON type information.
| This format prioritizes type preservation at the loss of human-readability and
interoperability with older formats.

* - **Relaxed Mode**
- | JSON representation that describes BSON documents with some type information loss.
| This format prioritizes human-readability and interoperability at the loss of
certain type information.

To learn more about JSON, BSON, and Extended JSON, see
`our article about JSON and BSON <https://www.mongodb.com/resources/basics/json-and-bson>`__
and :manual:`Extended JSON </reference/mongodb-extended-json/>` in the {+mdb-server+} manual.

.. _extended_json_example_section:

Extended JSON Examples
~~~~~~~~~~~~~~~~~~~~~~

The following examples show a document containing an ObjectId, date, and long
number field represented in the Extended JSON format. Click the tab that
corresponds to the format of the example you want to see:

.. tabs::

.. tab:: Extended
:tabid: extended-format

.. code-block:: json

{
"_id": { "$oid": "573a1391f29313caabcd9637" },
"createdAt": { "$date": { "$numberLong": "1601499609" }},
"numViews": { "$numberLong": "36520312" }
}

.. tab:: Relaxed Mode
:tabid: relaxed-mode-format

.. code-block:: json

{
"_id": { "$oid": "573a1391f29313caabcd9637" },
"createdAt": { "$date": "2020-09-30T18:22:51.648Z" },
"numViews": 36520312
}

Write Extended JSON
-------------------

You can write an Extended JSON string from a BSON document object by using the
``EJSON.stringify()`` method.

The following example outputs an Extended JSON string in the Relaxed format:

.. io-code-block::

.. input::
:language: js

import { Code, BSON } from 'mongodb';
const EJSON = BSON.EJSON;

const doc = {
foo: [1, 2],
bar: { hello: "world" },
code: new Code("function x() { return 1; }", {}),
date: new Date(2024, 6, 20, 10, 30, 0),
};

const ejsonStr = EJSON.stringify(doc);
console.log(ejsonStr);

.. output::
:language: none
:visible: false

{"foo":[1,2],"bar":{"hello":"world"},"code":{"$code":"function x() { return 1; }","$scope":{}},"date":{"$date":"2024-07-20T14:30:00Z"}}

By default, the ``stringify()`` method returns the Extended JSON string in the
Relaxed format. To specify the Canonical format, set the ``relaxed``
option to ``false``.

The following example shows how to output Extended JSON in the Canonical format:

.. io-code-block::

.. input::
:language: js

import { Code, BSON } from 'mongodb';
const EJSON = BSON.EJSON;

const doc = {
foo: [1, 2],
bar: { hello: "world" },
code: new Code("function x() { return 1; }", {}),
date: new Date(2024, 6, 20, 10, 30, 0),
};

const ejsonStr = EJSON.stringify(doc, { relaxed: false });
print(ejsonStr)

.. output::
:language: none
:visible: false

{"foo":[{"$numberInt":"1"},{"$numberInt":"2"}],"bar":{"hello":"world"},"code":{"$code":"function x() { return 1; }","$scope":{}},"date":{"$date":{"$numberLong":"1721485800000"}}}

Read Extended JSON
------------------

You can read an Extended JSON string into the JavaScript value or object described
by the string by using the ``EJSON.parse()`` method.

The following example shows how you can read an Extended JSON string into a
JavaScript value or object by using the ``parse()`` method:

.. The back ticks on ejsonStr in the below code example causes the orange
.. highlighting in this file, but the page still renders correctly.

.. io-code-block::

.. input::
:language: javascript

import { BSON } from 'mongodb';
const EJSON = BSON.EJSON;

const ejsonStr = `{
"foo": [
{ "$numberInt": "1" },
{ "$numberInt": "2" }
],
"bar": { "hello": "world" },
"code": {
"$code": "function x() { return 1; }",
"$scope": {}
},
"bin": { "$binary": { "base64": "AQIDBA==", "subType": "00" } }
}`;

const doc = EJSON.parse(ejsonStr);
console.log(doc);

.. output::
:language: none
:visible: false

{
foo: [ 1, 2 ],
bar: { hello: 'world' },
code: new Code('function x() { return 1; }', {}),
bin: Binary.createFromBase64('AQIDBA==', 0)
}

.. note::

The driver parses the ``$uuid`` Extended JSON type from a string to a
``BsonBinary`` object of binary subtype 4. For more information about ``$uuid`` field
parsing, see the
:spec:`Special Rules for Parsing $uuid Fields </extended-json/extended-json.md#special-rules-for-parsing-uuid-fields>`
section in the extended JSON specification.

API Documentation
-----------------

To learn more about any of the methods or types discussed in this
guide, see the `EJSON <https://github.com/mongodb/js-bson#ejson>`__ API documentation.