对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

使用扩展JSON数据

在本指南中,您可以学习;了解在与MongoDB文档交互时如何使用扩展JSON数据格式。

JSON是一种人类可读的数据格式,用于表示对象值、数组、数字、字符串、布尔值和空值。此格式仅支持BSON数据类型的子集,而MongoDB正是使用该格式来存储数据。扩展JSON格式支持更多BSON 类型,定义了一设立以 "$" 为前缀的保留键,用于表示直接对应于BSON中每种类型的字段类型信息。

要学习;了解有关JSON、 BSON和扩展JSON的更多信息,请参阅JSON和BSON资源以及扩展JSON MongoDB Server手册条目。

MongoDB扩展JSON提供字符串格式来表示BSON数据。 每种格式都符合JSON RFC 并满足特定的使用案例。

下表描述了每种扩展JSON格式:

名称
说明

扩展或规范

一种在数据转换过程中避免 BSON 类型信息丢失的 string 格式。
这种格式优先考虑类型保存,但会牺牲人类可读性以及与旧格式的互操作性。要了解有关此格式的更多信息,请参阅 API 文档中的 JsonMode.EXTENDED。

宽松

一种 string 格式,描述了丢失某些类型信息的 BSON 文档。
这种格式优先考虑人类可读性和互操作性,但会丢失某些类型的信息。Kotlin 同步驱动程序默认使用宽松模式。要了解有关此格式的更多信息,请参阅 API 文档中的 JsonMode.RELAXED。

Shell

与 MongoDB shell 中使用的语法相匹配的 string 格式。
这种格式优先考虑与 MongoDB shell 的兼容性,后者通常使用 JavaScript 函数来表示类型。有关这种格式的更多信息,请参阅 API 文档中的 JsonMode.SHELL。

注意

Kotlin 同步驱动程序将 $uuid 扩展 JSON 类型从 string 解析为二进制子类型 4 的 Binary 对象。有关 $uuid 字段解析的更多信息,请参阅扩展 JSON 规范中解析 $uuid 字段的特殊规则部分。

以下示例显示了包含对象标识符、日期和长数字字段的文档,这些字段分别以扩展 JSON 格式表示。单击与要查看的示例格式相对应的选项卡:

{ "_id": { "$oid": "573a1391f29313caabcd9637" }, "createdAt": { "$date": { "$numberLong": "1601499609" }}, "numViews": { "$numberLong": "36520312" }}

本节介绍如何通过以下方式将扩展JSON值读取到Kotlin对象中:

要将扩展JSON字符串读入Kotlin文档对象,请从 Document 或 BsonDocument 类中调用 parse() 静态方法。 此方法解析扩展JSON字符串并将其数据存储在指定文档类的实例中。

以下示例使用 parse() 方法将扩展JSON字符串读入 Document对象:

val ejsonStr = """ { "_id": { "$${"oid"}": "507f1f77bcf86cd799439011" }, "myNumber": { "$${"numberLong"}": "4794261" } }""".trimIndent() val doc = Document.parse(ejsonStr)println(doc)

要在不使用Kotlin Sync驱动程序的文档类的情况下将扩展JSON字符串读入Kotlin对象,请使用BSON库的 JsonReader 类。 此类包含用于按顺序解析扩展JSON字符串的字段和值并将它们作为Kotlin对象返回的方法。 驱动程序的文档类也使用此类来解析 扩展JSON。

以下代码使用 JsonReader 类提供的方法将扩展JSON字符串转换为Kotlin对象:

val string = """ { "_id": { "$${"oid"}": "507f1f77bcf86cd799439011" }, "myNumber": { "$${"numberLong"}": "4794261" } }""".trimIndent() val jsonReader = JsonReader(string)jsonReader.readStartDocument() // Reads the "_id" field valuejsonReader.readName("_id")val id = jsonReader.readObjectId() // Reads the "myNumber" field value jsonReader.readName("myNumber")val myNumber = jsonReader.readInt64() jsonReader.readEndDocument() println("$id is type: ${id::class.qualifiedName}")println("$myNumber is type: ${myNumber::class.qualifiedName}") jsonReader.close()

警告

在将 JSON 转换为 BSON 之前验证不受信任的输入

如果将 JSON string 转换为 BSON 并在查询、更新或命令中使用生成的 BSON,攻击者可以注入操作符或意外的字段值,从而改变操作的含义。当 JSON 来源于用户、API 请求或其他不可信的来源时,这种风险最大。

要了解有关在转换前验证输入的更多信息,请参阅 在将 JSON 转换为 BSON 之前验证不受信任的输入。

本节介绍如何通过以下方式从Kotlin对象写入扩展JSON值:

要从 Document 或 BsonDocument对象写入扩展JSON字符串,请调用 toJson() 方法。 您可以向此方法传递一个 JsonWriterSettings对象参数,以指定扩展JSON格式。

以下示例将 Document 数据写入为宽松模式扩展JSON:

val doc = Document() .append("_id", ObjectId("507f1f77bcf86cd799439012")) .append("createdAt", Date.from(Instant.ofEpochMilli(1601499609000L))) .append("myNumber", 4794261) val settings = JsonWriterSettings.builder() .outputMode(JsonMode.RELAXED) .build() println(doc.toJson(settings))

要从Kotlin对象中存储的数据输出扩展JSON字符串,您可以使用BSON库的 JsonWriter 类。 要构造 JsonWriter对象,请传递Java Writer 的子类以指定希望如何输出扩展JSON。(可选)您可以传递 JsonWriterSettings实例来指定选项,例如扩展JSON格式。默认下,JsonWriter 使用宽松模式格式。Kotlin Sync驱动程序的文档类也使用此类将BSON转换为扩展JSON。

以下示例使用 JsonWriter对象创建规范模式扩展JSON字符串值并将其输出到 System.out:

val settings = JsonWriterSettings.builder() .outputMode(JsonMode.EXTENDED) .build() JsonWriter(BufferedWriter(OutputStreamWriter(System.out)), settings).use { jsonWriter -> jsonWriter.writeStartDocument() jsonWriter.writeName("_id") jsonWriter.writeObjectId(ObjectId("507f1f77bcf86cd799439012")) jsonWriter.writeName("myNumber") jsonWriter.writeInt64(11223344L) jsonWriter.writeEndDocument() jsonWriter.flush()}

除了指定扩展JSON输出格式之外,您还可以通过向 JsonWriterSettings对象添加转换器来进一步自定义输出。这些转换器方法指定在转换进程中处理不同数据类型的逻辑。

以下示例转换与使用文档类示例相同的文档。但是,此示例在 JsonWriterSettings对象中定义了 objectIdConverter() 和 dateTimeConverter() 转换器方法,以简化宽松模式扩展JSON输出:

val settings = JsonWriterSettings.builder() .outputMode(JsonMode.RELAXED) .objectIdConverter { value, writer -> writer.writeString(value.toHexString()) } .dateTimeConverter { value, writer -> val zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC) writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime)) } .build() val doc = Document() .append("_id", ObjectId("507f1f77bcf86cd799439012")) .append("createdAt", Date.from(Instant.ofEpochMilli(1601499609000L))) .append("myNumber", 4794261) println(doc.toJson(settings))

要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: