文档数据格式:扩展 JSON
Overview
在本指南中,您可以了解如何在 MongoDB Kotlin 驱动程序中使用扩展 JSON 格式。
JSON 是一种数据格式,可表示对象值、数组值、数字值、字符串值、布尔值和空值。扩展 JSON 格式定义了一组以 “ $
” 为前缀的保留键,用于表示直接对应于 BSON 中每种类型的字段类型信息,BSON 是 MongoDB 用于存储数据的格式。
本指南解释了以下主题:
不同的 MongoDB 扩展 JSON 格式
如何使用 BSON 库在扩展 JSON 和 Kotlin 对象之间进行转换
如何创建 BSON 类型的自定义转换
有关这些格式之间差异的更多信息,请参阅我们关于 JSON 和 BSON 的文章。
扩展 JSON 格式
MongoDB 扩展 JSON 采用不同的字符串格式来表示 BSON 数据。每种不同的格式都符合 JSON RFC 并满足特定的用例。扩展格式也称为规范格式,使得每个 BSON 类型都具有特定表示形式,可进行双向转换而不会丢失信息。宽松模式格式更加简洁,更接近普通 JSON,但并不表示所有类型信息,比如数字字段的具体字节大小等。
请参阅下表查看每种格式的说明:
名称 | 说明 |
---|---|
扩展 | Also known as the canonical format, this JSON representation avoids loss of BSON type information. This format prioritizes type preservation at the loss of human-readability and interoperability with older formats. |
宽松模式 | JSON representation that describes BSON documents with some type information loss. This format prioritizes human-readability and interoperability at the loss of certain type information. |
Shell | JSON representation that matches the syntax used in the MongoDB shell. This format prioritizes compatibility with the MongoDB shell which often uses JavaScript functions to represent types. |
严格 | Deprecated. This representation is the legacy format that fully conforms to the JSON RFC which allows any JSON parser to read the type information. The legacy API uses this format. |
注意
驱动程序将 $uuid
扩展JSON类型从string解析为二进制子类型 4 的 BsonBinary
对象。 有关$uuid
字段解析的更多信息,请参阅 解析 $uuid 字段的特殊规则 扩展 JSON 规范中的 部分。
有关这些格式的详细信息,请参阅以下资源:
JSON RFC 官方文档
MongoDB 扩展 JSON 服务器手册条目
BsonBinary API 文档
扩展 JSON 规范 GitHub 文档
扩展 JSON 示例
以下示例显示了包含对象标识符、日期和长数字字段的文档,这些字段分别以扩展 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 文档对象,具体取决于您需要的 Realm 对象类型。此方法解析任何格式的扩展 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
。我们通过向 outputMode()
构建器方法传递 JsonMode.EXTENDED
常量来指定格式:
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 表达式的转换器,以简化宽松模式 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 文档: