|
| 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} |
0 commit comments