文档数据格式:扩展 JSON
概述
在本指南中,您可以学习如何在 MongoDB Java 驱动程序中使用扩展 JSON 格式。
JSON 是一种数据格式,用于表示对象、数组、数字、字符串、布尔值和 null 的值。扩展 JSON 格式定义了一组保留键,这些键以 "$" 前缀开头,用于表示字段类型信息,这些信息直接对应于 BSON 中的每个类型,BSON 是 MongoDB 用于存储数据的一种格式。$
表示字段类型信息,这些信息直接对应于 BSON 中的每个类型,BSON 是 MongoDB 用于存储数据的一种格式。
本指南解释了以下主题
不同的 MongoDB 扩展 JSON 格式
如何使用 BSON 库在扩展 JSON 和 Java 对象之间进行转换
如何创建自定义 BSON 类型转换
有关这些格式之间差异的更多信息,请参阅我们的关于 JSON 和 BSON 的文章.
扩展 JSON 格式
MongoDB 扩展 JSON 功能采用不同的字符串格式来表示 BSON 数据。每种不同的格式都符合 JSON RFC 标准,并满足特定的使用场景。所谓的 扩展 格式,也称为 规范 格式,为每种 BSON 类型提供特定的表示方式,以实现双向转换而不会丢失信息。 宽松模式 格式更加简洁,更接近普通 JSON,但并不表示所有类型信息,例如数字字段的特定字节大小。
请查看以下表格,了解每种格式的描述
名称 | 描述 |
---|---|
扩展 | 也称为 规范 格式,这种 JSON 表示法避免了 BSON 类型信息的丢失。 此格式以牺牲人类可读性和与旧格式互操作性为代价,优先保留了类型信息。 |
宽松模式 | 描述带有一些类型信息损失的 BSON 文档的 JSON 表示法。 此格式以牺牲某些类型信息为代价,优先考虑人类可读性和互操作性。 |
Shell | 与 MongoDB shell 中使用的语法匹配的 JSON 表示法。 此格式优先考虑与 MongoDB shell 的兼容性,MongoDB shell 通常使用 JavaScript 函数来表示类型。 |
严格 | 已弃用。 此表示法是符合 JSON RFC 的传统格式,它允许任何 JSON 解析器读取类型信息。 遗留 API 使用此格式。 |
注意
驱动程序将字符串中的扩展 JSON 类型 $uuid
解析为二进制子类型 4 的 BsonBinary
对象。有关 $uuid
字段解析的更多信息,请参阅扩展 JSON 规范中的解析 $uuid 字段的特殊规则 部分。
有关这些格式的更详细信息,请参阅以下资源
JSON RFC 官方文档
MongoDB Extended JSON 服务器手册条目
BsonBinary API 文档
扩展JSON规范 GitHub 文档
扩展JSON示例
以下示例显示了包含ObjectId、日期和长数字字段的文档,这些字段均以每种扩展JSON格式表示。点击您想查看的示例对应的选项卡
{ "_id": { "$oid": "573a1391f29313caabcd9637" }, "createdAt": { "$date": { "$numberLong": "1601499609" }}, "numViews": { "$numberLong": "36520312" } }
{ "_id": { "$oid": "573a1391f29313caabcd9637" }, "createdAt": { "$date": "2020-09-30T18:22:51.648Z" }, "numViews": 36520312 }
{ "_id": ObjectId("573a1391f29313caabcd9637"), "createdAt": ISODate("2020-09-30T18:22:51.648Z"), "numViews": NumberLong("36520312") }
{ "_id": { "$oid": "573a1391f29313caabcd9637" }, "createdAt": { "$date": 1601499609 }, "numViews": { "$numberLong": "36520312" } }
阅读扩展JSON
使用文档类
您可以通过调用来自Document
或BsonDocument
类的静态parse()
方法,将扩展JSON字符串读取到Java文档对象中,具体取决于所需的对象类型。此方法可以解析任何格式的扩展JSON字符串,并返回包含数据的该类的一个实例。
以下示例展示了如何使用Document
类通过parse()
方法将示例扩展JSON字符串读取到Document
对象中。
String ejsonStr = "{ \"_id\": { \"$oid\": \"507f1f77bcf86cd799439011\"}," + "\"myNumber\": {\"$numberLong\": \"4794261\" }}}"; Document doc = Document.parse(ejsonStr); System.out.println(doc);
Document{{_id=507f1f77bcf86cd799439011, myNumber=4794261}}
有关更多信息,请参阅我们的基础页面文档.
使用BSON库
您还可以使用JsonReader
类将扩展JSON字符串读取到Java对象中,而无需使用MongoDB Java驱动程序的文档类。此类包含用于逐个解析扩展JSON字符串中字段和值的方法,并将它们作为Java对象返回。驱动程序的文档类也使用此类来解析扩展JSON。
以下代码示例展示了如何使用JsonReader
类将扩展JSON字符串转换为Java对象。
String ejsonStr = "{ \"_id\": { \"$oid\": \"507f1f77bcf86cd799439011\"}," + "\"myNumber\": {\"$numberLong\": \"4794261\" }}}"; JsonReader jsonReader = new JsonReader(ejsonStr); jsonReader.readStartDocument(); jsonReader.readName("_id"); ObjectId id = jsonReader.readObjectId(); jsonReader.readName("myNumber"); Long myNumber = jsonReader.readInt64(); jsonReader.readEndDocument(); System.out.println(id + " is type: " + id.getClass().getName()); System.out.println(myNumber + " is type: " + myNumber.getClass().getName()); jsonReader.close();
507f1f77bcf86cd799439011 is type: org.bson.types.ObjectId 4794261 is type: java.lang.Long
有关更多信息,请参阅JsonReader API 文档。
编写扩展JSON
使用文档类
您可以通过调用toJson()
方法,从Document
或BsonDocument
实例中编写扩展JSON字符串,可选地传递一个JsonWriterSettings
实例来指定扩展JSON格式。
在此示例中,我们以宽松模式格式输出扩展JSON。
Document myDoc = new Document(); myDoc.append("_id", new ObjectId("507f1f77bcf86cd799439012")).append("myNumber", 11223344); JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build(); System.out.println(doc.toJson(settings));
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": 11223344}
使用BSON库
您还可以使用BSON库的JsonWriter
类从Java对象中的数据输出扩展JSON字符串。要通过JsonWriter
构造一个实例,传递一个Java Writer
的子类来指定如何输出扩展JSON。您可以可选地传递一个JsonWriterSettings
实例来指定选项,例如扩展JSON格式。默认情况下,JsonWriter
使用宽松模式格式。MongoDB Java驱动程序的文档类也使用此类将BSON转换为扩展JSON。
以下代码示例展示了如何使用JsonWriter
创建扩展JSON字符串并将其输出到System.out
。我们通过传递outputMode()
构建器方法JsonMode.EXTENDED
常量来指定格式
JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build(); try (JsonWriter jsonWriter = new JsonWriter(new BufferedWriter(new OutputStreamWriter(System.out)), settings)) { jsonWriter.writeStartDocument(); jsonWriter.writeObjectId("_id", new ObjectId("507f1f77bcf86cd799439012")); jsonWriter.writeInt64("myNumber", 11223344); jsonWriter.writeEndDocument(); jsonWriter.flush(); }
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": {"$numberLong": "11223344"}}
有关本节中提到的方法和类的更多信息,请参阅以下API文档
自定义BSON类型转换
除了指定 outputMode()
以格式化JSON输出外,您还可以通过向您的 JsonWriterSettings.Builder
中添加转换器来进一步自定义输出。这些转换器方法检测Java类型并执行传递给它们的 Converter
定义的逻辑。
以下示例代码显示了如何将作为lambda表达式定义的转换器附加到简化Relaxed模式JSON输出。
JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED) .objectIdConverter((value, writer) -> writer.writeString(value.toHexString())) .dateTimeConverter( (value, writer) -> { ZonedDateTime zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC); writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime)); }) .build(); Document doc = new Document() .append("_id", new ObjectId("507f1f77bcf86cd799439012")) .append("createdAt", Date.from(Instant.ofEpochMilli(1601499609000L))) .append("myNumber", 4794261); System.out.println(doc.toJson(settings)));
此代码的输出类似于以下文本
{"_id": "507f1f77bcf86cd799439012", "createdAt": "2020-09-30T21:00:09Z", "myNumber": 4794261}
未指定转换器时,Relaxed模式JSON输出类似于以下文本
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "createdAt": {"$date": "2020-09-30T21:00:09Z"}, "myNumber": 4794261}
有关本节中提到的方法和类的更多信息,请参阅以下API文档