Skip to main content

2. CBOR Data Models (CBOR 数据模型)

CBOR 明确定义了其通用数据模型 (Generic Data Model), 该模型定义了可以在 CBOR 中表示的所有数据项的集合. 其基本通用数据模型可通过注册 "简单值" (Simple Values) 和标签 (Tags) 进行扩展. 然后, 应用程序可以创建生成的扩展通用数据模型的子集, 以构建其特定数据模型 (Specific Data Models).

在可以表示通用数据模型中的数据项的环境中, 可以实现通用 CBOR 编码器和解码器 (这通常涉及为那些在环境中尚无自然表示的数据项定义额外的实现数据类型). 提供通用编码器和解码器的能力是 CBOR 的明确设计目标; 然而, 许多应用程序将提供自己的特定于应用程序的编码器和/或解码器.

在第 3 节中定义的基本 (未扩展) 通用数据模型中, 数据项是以下之一:

  • 范围在 -2^(64)..2^(64)-1 (包括两端) 内的整数

  • 简单值, 由 0 到 255 之间的数字标识, 但与该数字本身不同

  • 浮点值, 与整数不同, 来自 IEEE 754 binary64 可表示的集合 (包括非有限值) [IEEE754]

  • 零个或多个字节的序列 ("字节串", Byte String)

  • 零个或多个 Unicode 码点的序列 ("文本串", Text String)

  • 零个或多个数据项的序列 ("数组", Array)

  • 从零个或多个数据项 ("键", Keys) 到数据项 ("值", Values) 的映射 (数学函数) ("映射", Map)

  • 标记数据项 ("标签", Tag), 包含标签号 (范围在 0..2^(64)-1 内的整数) 和标签内容 (一个数据项)

请注意, 在此模型中, 整数值和浮点值是不同的, 即使它们具有相同的数值.

还要注意, 序列化变体在通用数据模型级别上是不可见的. 这种故意的不可见性包括编码浮点值的字节数. 它还包括 "参数" (argument) 的编码选择 (参见第 3 节), 例如整数的编码, 文本串或字节串长度的编码, 数组中元素数量或映射中键值对数量的编码, 或标签号的编码.

2.1. Extended Generic Data Models (扩展通用数据模型)

本文档通过注册一些简单值和标签号扩展了这个基本通用数据模型, 例如:

  • "false", "true", "null" 和 "undefined" (由 20..23 标识的简单值, 第 3.3 节)

  • 具有比上述更大范围和精度的整数和浮点值 (标签号 2 到 5, 第 3.4 节)

  • 应用程序数据类型, 例如 RFC 3339 中定义的时间点或日期/时间字符串 (标签号 1 和 0, 第 3.4 节)

扩展通用数据模型的其他元素可以 (并且已经) 通过为 CBOR 创建的 IANA 注册表定义. 即使通用编码器或解码器不知道这样的扩展, 使用该扩展的数据项也可以通过在基本通用数据模型中的应用程序接口表示它们来传递给应用程序或从应用程序传递, 即作为通用简单值或通用标签.

换句话说, 基本通用数据模型在本文档中定义后是稳定的, 而扩展通用数据模型通过注册新的简单值或标签号而扩展, 但永远不会缩小.

虽然人们强烈期望通用编码器和解码器能够以适合其编程环境的形式表示 "false", "true" 和 "null" ("undefined" 被有意省略), 但由标签创建的数据模型扩展的实现确实是可选的, 并且是实现质量的问题.

2.2. Specific Data Models (特定数据模型)

基于 CBOR 的协议的特定数据模型通常采用扩展通用数据模型的子集, 并将应用程序语义分配给此子集及其组件中的数据项. 在记录此类特定数据模型并指定数据项类型时, 最好通过其通用数据模型名称 ("负整数" (Negative Integer), "数组" (Array)) 来标识类型, 而不是引用其 CBOR 表示的方面 ("主类型 1" (Major Type 1), "主类型 4" (Major Type 4)).

特定数据模型还可以为映射键和编码器自由度指定值等价性 (包括不同类型的值). 例如, 在通用数据模型中, 有效映射可以同时具有 "0" 和 "0.0" 作为键, 并且编码器不得将 "0.0" 编码为整数 (主类型 0, 第 3.1 节). 但是, 如果特定数据模型声明整数值的浮点表示和整数表示是等价的, 则在单个映射中使用 "0" 和 "0.0" 两个键将被视为重复, 即使编码为不同的主类型, 因此无效; 并且编码器可以将整数值浮点数编码为整数或反之亦然, 也许是为了节省编码字节.