fxamacker/cbor
GitHub: fxamacker/cbor
一个符合 RFC 8949 标准的高性能 Go 语言 CBOR 编解码库,提供安全、紧凑的二进制序列化能力。
Stars: 1069 | Forks: 81
[fxamacker/cbor](https://github.com/fxamacker/cbor) 是一个用于编码和解码 [CBOR](https://www.rfc-editor.org/info/std94) 和 [CBOR Sequences](https://www.rfc-editor.org/rfc/rfc8742.html) 的库。
CBOR 是 JSON、MessagePack、Protocol Buffers 等格式的一个[可靠替代方案](https://www.rfc-editor.org/rfc/rfc8949.html#name-comparison-of-other-binary-)。CBOR 是由 [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94) 定义的互联网标准,其设计旨在保持数十年的适用性。
`fxamacker/cbor` 被应用于 Arm Ltd.、EdgeX Foundry、Flow Foundation、Fraunhofer-AISEC、IBM、Kubernetes[*](https://github.com/search?q=org%3Akubernetes%20fxamacker%2Fcbor&type=code)、Let's Encrypt、Linux Foundation、Microsoft、Oasis Protocol、Red Hat[*](https://github.com/search?q=org%3Aopenshift+fxamacker%2Fcbor&type=code)、Tailscale[*](https://github.com/search?q=org%3Atailscale+fxamacker%2Fcbor&type=code)、Veraison[*](https://github.com/search?q=org%3Averaison+fxamacker%2Fcbor&type=code) [等](https://github.com/fxamacker/cbor#who-uses-fxamackercbor) 的项目中。
请参阅[快速开始](#quick-start)和[发布版本](https://github.com/fxamacker/cbor/releases/)。 🆕 `UnmarshalFirst` 和 `DiagnoseFirst` 可以解码 CBOR Sequences。 `MarshalToBuffer` 和 `UserBufferEncMode` 接受用户指定的 buffer。
## fxamacker/cbor
[](https://github.com/fxamacker/cbor/actions?query=workflow%3Aci)
[](https://github.com/fxamacker/cbor/actions?query=workflow%3A%22cover+%E2%89%A597%25%22)
[](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml)
[](#fuzzing-and-code-coverage)
[](https://goreportcard.com/report/github.com/fxamacker/cbor)
[](https://github.com/fxamacker/cbor#fuzzing-and-code-coverage)
`fxamacker/cbor` 是一个完全符合 [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94) 的 CBOR 编解码器。它还支持 CBOR Sequences([RFC 8742](https://www.rfc-editor.org/rfc/rfc8742.html))和扩展诊断表示法([Appendix G of RFC 8610](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G))。
API 与 `encoding/json` 基本相同,并增加了简化并发和 CBOR 选项的接口。
设计在安全性、速度、并发性、编码数据大小、可用性等方面进行了平衡与取舍。
### 通过可配置设置进行安全解码
`fxamacker/cbor` 具有可配置的限制等功能,可防御恶意的 CBOR 数据。
值得注意的是,`fxamacker/cbor` 在拒绝格式错误的 CBOR 数据时速度非常快。
相比之下,某些编解码器在解码坏数据时可能会崩溃或占用过多资源。
### 使用 Struct Tag 选项实现更小的编码
Struct tag 会自动减小 struct 的编码大小并提高速度。
我们可以通过使用 struct tag 选项来减少代码编写量:
- `toarray`:编码时不包含字段名(解码还原为原始 struct)
- `keyasint`:将字段名编码为整数(解码还原为原始 struct)
- `omitempty`:编码时忽略空字段
- `omitzero`:编码时忽略零值字段
作为一种特殊情况,struct 字段 tag "-" 会忽略该字段。
注意:当 struct 使用 `toarray` 时,编码器将忽略 `omitempty` 和 `omitzero`,以防止编码后数组元素的位置发生改变。这使得解码器能够将编码后的元素与其 Go struct 字段匹配。

## 快速开始
__安装__:`go get github.com/fxamacker/cbor/v2` 并 `import "github.com/fxamacker/cbor/v2"`。
### 关键点
该库可以编码和解码 CBOR (RFC 8949) 以及 CBOR Sequences (RFC 8742)。
- __CBOR data item__ 是单个 CBOR 数据,其结构可能包含 0 个或多个嵌套的 data item。
- __CBOR sequence__ 是 0 个或多个已编码 CBOR data item 的拼接。
可配置的限制和选项可用于平衡各项取舍。
- 编码和解码模式由选项(设置)创建。
- 可以在启动时创建模式并重复使用。
- 模式对于并发使用是安全的。
### 默认模式
包级别的函数仅使用该库的默认设置。
它们提供了编码和解码的“默认模式”。
```
// API matches encoding/json for Marshal, Unmarshal, Encode, Decode, etc.
b, err = cbor.Marshal(v) // encode v to []byte b
err = cbor.Unmarshal(b, &v) // decode []byte b to v
decoder = cbor.NewDecoder(r) // create decoder with io.Reader r
err = decoder.Decode(&v) // decode a CBOR data item to v
// v2.7.0 added MarshalToBuffer() and UserBufferEncMode interface.
err = cbor.MarshalToBuffer(v, b) // encode v to b instead of using built-in buf pool.
// v2.5.0 added new functions that return remaining bytes.
// UnmarshalFirst decodes first CBOR data item and returns remaining bytes.
rest, err = cbor.UnmarshalFirst(b, &v) // decode []byte b to v
// DiagnoseFirst translates first CBOR data item to text and returns remaining bytes.
text, rest, err = cbor.DiagnoseFirst(b) // decode []byte b to Diagnostic Notation text
// NOTE: Unmarshal() returns ExtraneousDataError if there are remaining bytes, but
// UnmarshalFirst() and DiagnoseFirst() allow trailing bytes.
```
### 预设
预设可以直接使用,也可以作为自定义设置的起点。
```
// EncOptions is a struct of encoder settings.
func CoreDetEncOptions() EncOptions // RFC 8949 Core Deterministic Encoding
func PreferredUnsortedEncOptions() EncOptions // RFC 8949 Preferred Serialization
func CanonicalEncOptions() EncOptions // RFC 7049 Canonical CBOR
func CTAP2EncOptions() EncOptions // FIDO2 CTAP2 Canonical CBOR
```
预设用于创建自定义模式。
### 自定义模式
模式由设置创建。一旦创建,模式的设置将不可变。
💡 在启动时创建模式并重复使用它。它对于并发使用是安全的。
```
// Create encoding mode.
opts := cbor.CoreDetEncOptions() // use preset options as a starting point
opts.Time = cbor.TimeUnix // change any settings if needed
em, err := opts.EncMode() // create an immutable encoding mode
// Reuse the encoding mode. It is safe for concurrent use.
// API matches encoding/json.
b, err := em.Marshal(v) // encode v to []byte b
encoder := em.NewEncoder(w) // create encoder with io.Writer w
err := encoder.Encode(v) // encode v to io.Writer w
```
默认模式和自定义模式会自动应用 struct tag。
### 用户指定的编码 Buffer (v2.7.0)
`UserBufferEncMode` 接口扩展了 `EncMode` 接口,增加了 `MarshalToBuffer()`。它接受用户指定的 buffer,而不是使用内置的 buffer 池。
```
em, err := myEncOptions.UserBufferEncMode() // create UserBufferEncMode mode
var buf bytes.Buffer
err = em.MarshalToBuffer(v, &buf) // encode v to provided buf
```
### Struct Tags
Struct tag 选项(`toarray`、`keyasint`、`omitempty`、`omitzero`)可减小 struct 的编码大小。
作为一种特殊情况,struct 字段 tag "-" 会忽略该字段。
Struct tag 选项简化了基于 CBOR 且需要 CBOR 数组或带有整数 key 的 map 的协议的使用。
### CBOR Tags
CBOR tags 在 `TagSet` 中指定。
可以使用 `TagSet` 创建自定义模式来处理 CBOR tags。
```
em, err := opts.EncMode() // no CBOR tags
em, err := opts.EncModeWithTags(ts) // immutable CBOR tags
em, err := opts.EncModeWithSharedTags(ts) // mutable shared CBOR tags
```
`TagSet` 及使用它的模式对于并发使用是安全的。 `DecMode` 也提供了等效的 API。
👉 `fxamacker/cbor` 允许用户应用通过实现 `cbor.Marshaler` 和 `cbor.Unmarshaler` 接口,来使用几乎所有当前或未来的 CBOR tag 编号。
基本上,用户应用可以实现 `MarshalCBOR` 和 `UnmarshalCBOR` 函数,这些函数将被此 CBOR 编解码器的 `Marshal`、`Unmarshal` 等方法自动调用。
以下[示例](https://github.com/fxamacker/cbor/blob/master/example_embedded_json_tag_for_cbor_test.go)展示了如何编码和解码 tag 编号为 262 的带标签 CBOR data item。该 tag 内容是一个作为 CBOR byte string(major type 2)“嵌入”的 JSON 对象。
### 函数与接口
### 安全提示
🔒 在解码非常大或不确定大小的数据时,使用 Go 的 `io.LimitReader` 来限制大小。
对于处理超大数据(例如区块链)的系统,可能需要增加默认限制。
可以使用 `DecOptions` 来修改 `MaxArrayElements`、`MaxMapPairs` 和 `MaxNestedLevels` 的默认限制。
## 状态
v2.9.2(2026年5月3日,星期日)通过为编码到 CBOR indefinite-length 数据添加更严格的检查,重构并强化了流式编码器。这防止了对本库的不当使用生成出会被解码器拒绝的格式错误的 CBOR indefinite-length 数据。
此版本包含其他 bug 修复、防御性检查,并增加了更多测试。
v2.9.0 通过了 fuzz 测试(数十亿次执行),具备生产级质量。
更多详情,请参阅 [v2.9.2 发布说明](https://github.com/fxamacker/cbor/releases)。
### 早期版本
发布和提交通常在星期日进行,因为我的工作日程使得我在工作日(有时甚至是连续的周末和连续的圣诞假期)没有时间处理这个项目。星期一早上的发布是为了在点击发布按钮之前,允许进行更多的夜间 fuzz 测试。
[v2.9.1](https://github.com/fxamacker/cbor/releases/tag/v2.9.1)(2026年3月30日,星期一)包含重要的 bug 修复、防御性检查、改进的代码质量以及更多测试。虽然没有公开,但 fuzzer 也通过添加更多 fuzz 测试得到了改进。它通过了 fuzz 测试(数十亿次执行),具备生产级质量。
[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0)(2025年7月13日,星期日)改进了 CBOR 和 JSON 之间的互操作性/转码,重构了测试,并改进了文档。它通过了 fuzz 测试(数十亿次执行),具备生产级质量。
[v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0)(2025年3月30日,星期日)是一个小版本发布,主要是为了向 struct 字段 tag 添加 `omitzero` 选项并修复 bug。它通过了 fuzz 测试(数十亿次执行),具备生产级质量。
[v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0)(2024年6月23日,星期一)增加了帮助大型项目(例如 Kubernetes)将 CBOR 用作 JSON 和 Protocol Buffers 替代方案的功能和改进。其他改进包括加速、改善内存使用、修复 bug、新的序列化等。它通过了 fuzz 测试(超过 50 亿次执行),具备生产级质量。
[v2.6.0](https://github.com/fxamacker/cbor/releases/tag/v2.6.0)(2024年2月11日,星期日)增加了重要的新功能、优化和 bug 修复。它对于需要在 CBOR 和 JSON 之间转换数据的系统尤其有用。新的选项和优化改进了对 bignum、整数、map 和 string 的处理。
[v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0)(2023年8月13日,星期日)增加了新功能和重要的 bug 修复。在经过长期测试的 beta 版本 [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta)(2022年12月) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0)(2023年8月)之后,它经过了 fuzz 测试并具备生产级质量。
__重要__: 👉 在从 v2.4 或更早版本升级之前,请阅读发布说明中强调的重大变更。 v2.5.0 是一个大版本发布,修复了 `Unmarshal` 中处理冗余数据等行为的 bug,在升级前应进行审查。
有关新功能、改进和 bug 修复的列表,请参阅 [v2.5.0 发布说明](https://github.com/fxamacker/cbor/releases/tag/v2.5.0)。
有关版本号等的更多信息,请参阅[“版本与 API 变更”](https://github.com/fxamacker/cbor#versions-and-api-changes)部分。