文档数据格式:扩展JSON
概述
在这份指南中,您可以学习如何在MongoDB Kotlin驱动程序中使用扩展JSON格式。
JSON是一种数据格式,用于表示对象、数组、数字、字符串、布尔值和null的值。扩展JSON格式定义了一个保留键集合,以"$"前缀开始,用于表示与BSON中每个类型直接对应的字段类型信息。$
代表字段类型信息,它与BSON格式相对应,这是MongoDB用于存储数据的一种格式。
本指南解释以下主题:
不同的MongoDB扩展JSON格式
如何使用BSON库在扩展JSON和Kotlin对象之间进行转换
如何创建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使用此格式。 |
注意
驱动程序将Extended JSON类型中的 $uuid
从字符串解析到二进制子类型4的 BsonBinary
对象。有关 $uuid
字段解析的更多信息,请参阅 解析$uuid字段的特殊规则 部分在扩展JSON规范中。
有关这些格式的更详细信息,请参阅以下资源
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 字符串读取到 Kotlin 文档对象中。此方法可以解析任何格式的扩展 JSON 字符串,并返回包含数据的该类的实例。
以下示例展示了如何使用 Document
类通过 parse()
方法将示例扩展 JSON 字符串读取到 Document
对象中。
val ejsonStr = """ { "_id": { "${"$"}oid": "507f1f77bcf86cd799439011"}, "myNumber": {"${"$"}numberLong": "4794261" }} """.trimIndent() val doc = Document.parse(ejsonStr) println(doc)
Document{{_id=507f1f77bcf86cd799439011, myNumber=4794261}}
有关更多信息,请参阅我们的基础页面文档.
使用 BSON 库
您还可以使用 JsonReader
类将扩展 JSON 字符串读取到 Kotlin 对象中,而不需要使用 MongoDB Kotlin 驱动的文档类。此类包含用于逐个解析扩展 JSON 字符串中的字段和值的格式的方法,并将它们作为 Kotlin 对象返回。驱动程序的文档类也使用此类来解析扩展 JSON。
以下代码示例展示了如何使用 JsonReader
类将扩展 JSON 字符串转换为 Kotlin 对象。
val ejsonStr = """ { "_id": { "${"$"}oid": "507f1f77bcf86cd799439011"}, "myNumber": {"${"$"}numberLong": "4794261" }} """.trimIndent() val jsonReader = JsonReader(ejsonStr) jsonReader.readStartDocument() jsonReader.readName("_id") val id = jsonReader.readObjectId() jsonReader.readName("myNumber") val myNumber = jsonReader.readInt64() jsonReader.readEndDocument() println(id.toString() + " is type: " + id.javaClass.name) println(myNumber.toString() + " is type: " + myNumber.javaClass.name) 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。
val myDoc = Document().append("_id", ObjectId("507f1f77bcf86cd799439012")) .append("myNumber", 11223344) val settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build() myDoc.toJson(settings)
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": 11223344}
使用BSON库
您还可以使用BSON库和JsonWriter
类从Kotlin对象中的数据输出扩展JSON字符串。要构建一个JsonWriter
实例,传递一个Java Writer
子类来指定您想要如何输出扩展JSON。您可以可选地传递一个JsonWriterSettings
实例来指定选项,例如扩展JSON格式。默认情况下,JsonWriter
使用宽松模式格式。MongoDB Kotlin驱动程序的文档类也使用此类将BSON转换为扩展JSON。
以下代码示例展示了如何使用JsonWriter
来创建扩展的JSON字符串并将其输出到System.out
。我们通过将JsonMode.EXTENDED
常量传递给outputMode()
构建器方法来指定格式。
val settings = JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build() JsonWriter(BufferedWriter(OutputStreamWriter(System.out)), settings).use { jsonWriter -> jsonWriter.writeStartDocument() jsonWriter.writeObjectId("_id", ObjectId("507f1f77bcf86cd799439012")) jsonWriter.writeInt64("myNumber", 11223344) jsonWriter.writeEndDocument() jsonWriter.flush() }
{"_id": {"$oid": "507f1f77bcf86cd799439012"}, "myNumber": {"$numberLong": "11223344"}}
有关本节中提到的方法和类的更多信息,请参阅以下API文档。
自定义BSON类型转换
除了指定outputMode()
来格式化JSON输出外,您还可以通过向您的JsonWriterSettings.Builder
添加转换器来进一步自定义输出。这些转换器方法检测Kotlin类型,并执行传递给它们的Converter
中定义的逻辑。
以下示例代码展示了如何将作为lambda表达式定义的转换器添加到Relaxed模式JSON输出中。
val settings = JsonWriterSettings.builder() .outputMode(JsonMode.RELAXED) .objectIdConverter { value, writer -> writer.writeString(value.toHexString()) } .timestampConverter { value, writer -> val ldt = LocalDateTime.ofInstant(Instant.ofEpochSecond(value.time.toLong()), ZoneOffset.UTC) writer.writeString(ldt.format(DateTimeFormatter.ISO_DATE_TIME)) } .build() val doc = Document() .append("_id", ObjectId("507f1f77bcf86cd799439012")) .append("createdAt", BsonTimestamp(1601516589,1)) .append("myNumber", 4794261) println(doc.toJson(settings))
{"_id": "507f1f77bcf86cd799439012", "createdAt": "2020-10-01T01:43:09", "myNumber": 4794261} // Without specifying the converters, the Relaxed mode JSON output // should look something like this: {"_id": {"$oid": "507f1f77bcf86cd799439012"}, "createdAt": {"$timestamp": {"t": 1601516589, "i": 1}}, "myNumber": 4794261}
有关本节中提到的方法和类的更多信息,请参阅以下API文档。