Skip to content

Commit 69544cd

Browse files
committed
DOCSP-51341: Extended JSON
1 parent 546c88e commit 69544cd

File tree

4 files changed

+299
-5
lines changed

4 files changed

+299
-5
lines changed

snooty.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ api-root = "https://mongodb.github.io/mongo-java-driver/{+version-number+}/apido
3333
driver-api = "{+api-root+}/driver-kotlin-sync/mongodb-driver-kotlin-sync/com.mongodb.kotlin.client"
3434
core-api = "{+api-root+}/driver-core/com/mongodb"
3535
kotlin-docs = "https://kotlinlang.org"
36+
bson-api =
3637
serialization-version = "1.6.0"
3738
kotlinx-dt-version = "0.6.1"
3839
mongocrypt-version = "{+full-version+}"

source/data-formats.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ Data Formats
2525
Data Classes </data-formats/data-format-data-class>
2626
BSON </data-formats/bson>
2727
Time Series </data-formats/time-series>
28-
29-
.. TODO: /data-formats/extended-json
28+
Extended JSON </data-formats/extended-json>
3029

3130
Overview
3231
--------
@@ -49,6 +48,4 @@ sections:
4948
:ref:`kotlin-sync-data-format-data-classes` guide.
5049
- Learn how to work with the BSON data format in the :ref:`kotlin-sync-bson` guide.
5150
- Learn how to store and interact with time series data in the :ref:`kotlin-sync-time-series` guide.
52-
53-
.. TODO: Uncomment these as pages get built
54-
.. - Learn how to use the Extended JSON format in the :ref:`kotlin-sync-extended-json` guide.
51+
- Learn how to read and write Extended JSON strings in the :ref:`kotlin-sync-extended-json` guide.

source/data-formats/extended-json.txt

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
.. _kotlin-sync-extended-json:
2+
3+
============================
4+
Work with Extended JSON Data
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
19+
20+
.. sharedinclude:: dbx/extended-json.rst
21+
22+
.. replacement:: driver-specific-text-relaxed
23+
24+
The {+driver-short+} uses Relaxed mode by default.
25+
26+
Read Extended JSON
27+
------------------
28+
29+
This section shows how to read Extended JSON values into {+language+}
30+
objects in the following ways:
31+
32+
- :ref:`kotlin-sync-read-ejson-doc`
33+
- :ref:`kotlin-sync-read-ejson-jsonreader`
34+
35+
.. _kotlin-sync-read-ejson-doc:
36+
37+
Use the Document Classes
38+
~~~~~~~~~~~~~~~~~~~~~~~~
39+
40+
To read a Extended JSON string into a {+language+} document object, call
41+
the ``parse()`` static method from the ``Document`` or ``BsonDocument`` class.
42+
This method parses the Extended JSON string and stores its data in an instance of the specified
43+
document class.
44+
45+
The following example uses the ``parse()`` method to read an Extended JSON string
46+
into a ``Document`` object:
47+
48+
.. io-code-block::
49+
:copyable:
50+
51+
.. input:: /includes/data-formats/ext-json.kt
52+
:language: kotlin
53+
:start-after: start-read-doc
54+
:end-before: end-read-doc
55+
:dedent:
56+
57+
.. output::
58+
:visible: false
59+
60+
Document{{_id=507f1f77bcf86cd799439011, myNumber=4794261}}
61+
62+
.. _kotlin-sync-read-ejson-jsonreader:
63+
64+
Use the JsonReader Class
65+
~~~~~~~~~~~~~~~~~~~~~~~~
66+
67+
To read an Extended JSON string into {+language+} objects without using
68+
the {+driver-short+}'s document classes, use the BSON library's ``JsonReader`` class.
69+
This class contains methods to sequentially parse the fields and values
70+
of the Extended JSON string and return them as {+language+} objects.
71+
The driver's document classes also use this class to parse Extended JSON.
72+
73+
The following code uses methods provided by the ``JsonReader`` class to convert
74+
an Extended JSON string into {+language+} objects:
75+
76+
.. io-code-block::
77+
:copyable:
78+
79+
.. input:: /includes/data-formats/ext-json.kt
80+
:language: kotlin
81+
:start-after: start-read-bson
82+
:end-before: end-read-bson
83+
:dedent:
84+
85+
.. output::
86+
:visible: false
87+
88+
507f1f77bcf86cd799439011 is type: org.bson.types.ObjectId
89+
4794261 is type: kotlin.Long
90+
91+
Write Extended JSON
92+
-------------------
93+
94+
This section shows how to write Extended JSON values from {+language+}
95+
objects in the following ways:
96+
97+
- :ref:`kotlin-sync-write-ejson-doc`
98+
- :ref:`kotlin-sync-write-ejson-jsonwriter`
99+
100+
.. _kotlin-sync-write-ejson-doc:
101+
102+
Use the Document Classes
103+
~~~~~~~~~~~~~~~~~~~~~~~~
104+
105+
To write an Extended JSON string from a ``Document`` or ``BsonDocument``
106+
object, call the ``toJson()`` method. You can pass this method a
107+
``JsonWriterSettings`` object parameter to specify the Extended JSON format.
108+
109+
The following example writes ``Document`` data as Relaxed mode Extended
110+
JSON:
111+
112+
.. io-code-block::
113+
:copyable:
114+
115+
.. input:: /includes/data-formats/ext-json.kt
116+
:language: kotlin
117+
:start-after: start-write-doc
118+
:end-before: end-write-doc
119+
:dedent:
120+
121+
.. output::
122+
:visible: false
123+
124+
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": 11223344}
125+
126+
.. _kotlin-sync-write-ejson-jsonwriter:
127+
128+
Use the JsonWriter Class
129+
~~~~~~~~~~~~~~~~~~~~~~~~
130+
131+
To output an Extended JSON string from data stored in {+language+} objects, use
132+
the BSON library's ``JsonWriter`` class. To construct a ``JsonWriter`` object,
133+
pass a subclass of a Java ``Writer`` to specify how you want to output the Extended
134+
JSON. Optionally, you can pass a ``JsonWriterSettings`` instance to specify options,
135+
such as the Extended JSON format. By default, ``JsonWriter`` uses the Relaxed mode
136+
format. The {+driver-short+}'s document classes also use this class to convert BSON
137+
to Extended JSON.
138+
139+
The following example uses a ``JsonWriter`` object to create
140+
Canonical mode Extended JSON string values and output them to ``System.out``:
141+
142+
.. io-code-block::
143+
:copyable:
144+
145+
.. input:: /includes/data-formats/ext-json.kt
146+
:language: kotlin
147+
:start-after: start-write-bson
148+
:end-before: end-write-bson
149+
:dedent:
150+
151+
.. output::
152+
:visible: false
153+
154+
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": {"$numberLong": "11223344"}}
155+
156+
Custom BSON Type Conversion
157+
---------------------------
158+
159+
In addition to specifying the Extended JSON output format, you
160+
can further customize the output by adding converters to your
161+
``JsonWriterSettings`` object. These converter methods specify logic
162+
for handling different data types during the conversion process.
163+
164+
The following example defines the ``objectIdConverter()`` and ``dateTimeConverter()``
165+
converter methods in a ``JsonWriterSettings`` object to simplify the Relaxed mode
166+
Extended JSON output:
167+
168+
.. io-code-block::
169+
:copyable:
170+
171+
.. input:: /includes/data-formats/ext-json.kt
172+
:language: kotlin
173+
:start-after: start-custom-conversion
174+
:end-before: end-custom-conversion
175+
:dedent:
176+
177+
.. output::
178+
:visible: false
179+
180+
{"_id": "507f1f77bcf86cd799439012", "createdAt": "2020-09-30T21:00:09Z", "myNumber": 4794261}
181+
182+
API Documentation
183+
-----------------
184+
185+
To learn more about any of the methods or types discussed in this
186+
guide, see the following API documentation:
187+
188+
- `Document <{+api-root+}/bson/org/bson/Document.html>`__
189+
- `Document.parse() <{+api-root+}/bson/org/bson/Document.html#parse(java.lang.String)>`__
190+
- `JsonReader <{+api-root+}/bson/org/bson/json/JsonReader.html>`__
191+
- `JsonWriter <{+api-root+}/bson/org/bson/json/JsonWriter.html>`__
192+
- `Document.toJson() <{+api-root+}/bson/org/bson/Document.html#toJson()>`__
193+
- `JsonWriterSettings <{+api-root+}/bson/org/bson/json/JsonWriterSettings.html>`__
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package org.example
2+
3+
import org.bson.json.JsonWriter
4+
import org.bson.json.JsonWriterSettings
5+
import java.util.Date
6+
import org.bson.Document
7+
import org.bson.json.JsonMode
8+
import org.bson.json.JsonReader
9+
import org.bson.types.ObjectId
10+
import java.time.Instant
11+
import java.time.ZoneOffset
12+
import java.time.format.DateTimeFormatter
13+
import java.io.BufferedWriter
14+
import java.io.OutputStreamWriter
15+
16+
fun main() {
17+
18+
// start-read-doc
19+
val ejsonStr = """
20+
{
21+
"_id": { "$${"oid"}": "507f1f77bcf86cd799439011" },
22+
"myNumber": { "$${"numberLong"}": "4794261" }
23+
}
24+
""".trimIndent()
25+
26+
val doc = Document.parse(ejsonStr)
27+
println(doc)
28+
// end-read-doc
29+
30+
// start-read-bson
31+
val string = """
32+
{
33+
"_id": { "$${"oid"}": "507f1f77bcf86cd799439011" },
34+
"myNumber": { "$${"numberLong"}": "4794261" }
35+
}
36+
""".trimIndent()
37+
38+
val jsonReader = JsonReader(string)
39+
40+
jsonReader.readStartDocument()
41+
42+
jsonReader.readName("_id")
43+
val id = jsonReader.readObjectId()
44+
45+
jsonReader.readName("myNumber")
46+
val myNumber = jsonReader.readInt64()
47+
48+
jsonReader.readEndDocument()
49+
50+
println("$id is type: ${id::class.qualifiedName}")
51+
println("$myNumber is type: ${myNumber::class.qualifiedName}")
52+
53+
jsonReader.close()
54+
// end-read-bson
55+
56+
// start-write-doc
57+
val myDoc = Document()
58+
.append("_id", ObjectId("507f1f77bcf86cd799439012"))
59+
.append("myNumber", 11223344)
60+
61+
val settings = JsonWriterSettings.builder()
62+
.outputMode(JsonMode.RELAXED)
63+
.build()
64+
65+
println(myDoc.toJson(settings))
66+
// end-write-doc
67+
68+
// start-write-bson
69+
val settings = JsonWriterSettings.builder()
70+
.outputMode(JsonMode.EXTENDED)
71+
.build()
72+
73+
JsonWriter(BufferedWriter(OutputStreamWriter(System.out)), settings).use { jsonWriter ->
74+
jsonWriter.writeStartDocument()
75+
jsonWriter.writeName("_id")
76+
jsonWriter.writeObjectId(ObjectId("507f1f77bcf86cd799439012"))
77+
jsonWriter.writeName("myNumber")
78+
jsonWriter.writeInt64(11223344L)
79+
jsonWriter.writeEndDocument()
80+
jsonWriter.flush()
81+
}
82+
// end-write-bson
83+
84+
// start-custom-conversion
85+
val settings = JsonWriterSettings.builder()
86+
.outputMode(JsonMode.RELAXED)
87+
.objectIdConverter { value, writer ->
88+
writer.writeString(value.toHexString())
89+
}
90+
.dateTimeConverter { value, writer ->
91+
val zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC)
92+
writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime))
93+
}
94+
.build()
95+
96+
val doc = Document()
97+
.append("_id", ObjectId("507f1f77bcf86cd799439012"))
98+
.append("createdAt", Date.from(Instant.ofEpochMilli(1601499609000L)))
99+
.append("myNumber", 4794261)
100+
101+
println(doc.toJson(settings))
102+
// end-custom-conversion
103+
}

0 commit comments

Comments
 (0)