文档菜单
文档首页
/ / /
Kotlin 协程
/ /

文档数据格式:扩展JSON

本页内容

  • 概述
  • 扩展JSON格式
  • 扩展JSON示例
  • 读取扩展JSON
  • 使用文档类
  • 使用BSON库
  • 写入扩展JSON
  • 使用文档类
  • 使用BSON库
  • 自定义BSON类型转换

在这份指南中,您可以学习如何在MongoDB Kotlin驱动程序中使用扩展JSON格式。

JSON是一种数据格式,用于表示对象、数组、数字、字符串、布尔值和null的值。扩展JSON格式定义了一个保留键集合,以"$"前缀开始,用于表示与BSON中每个类型直接对应的字段类型信息。$代表字段类型信息,它与BSON格式相对应,这是MongoDB用于存储数据的一种格式。

本指南解释以下主题:

  • 不同的MongoDB扩展JSON格式

  • 如何使用BSON库在扩展JSON和Kotlin对象之间进行转换

  • 如何创建BSON类型的自定义转换

有关这些格式之间差异的更多信息,请参阅我们的关于JSON和BSON的文章.

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规范中。

有关这些格式的更详细信息,请参阅以下资源

以下示例显示了包含 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" }
}

您可以通过调用来自 DocumentBsonDocument 类的静态方法 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}}

有关更多信息,请参阅我们的基础页面文档.

您还可以使用 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 文档。

您可以通过调用toJson()方法从DocumentBsonDocument实例中编写扩展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库和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文档。

除了指定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文档。

返回

BSON