首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 归档 标签 关于

新的 JSON Go API

摘要

Michael Pratt, Joe Tsai, Daniel Martí, Johan Brandhorst-Satzkorn, Roger Peppe, Chris Hines, and Damien Neil 4 November 2026 Introduction JavaScript Object Notation (JSON) is a simple data interchange ...

the and JSON encoding json with has for data years
2026-11-05 1 阅读 约6分钟阅读 olexsmir
分享:
字号:
Michael Pratt、Joe Tsai、Daniel Martí、Johan Brandhorst-Satzkorn、Roger Peppe、Chris Hines 和 Damien Neil 2026 年 11 月 4 日 简介 JavaScript 对象表示法 (JSON) 是一种简单的数据交换格式,是互联网上最流行的数据格式,并被 Go 程序广泛读取和编写。早在 Go 1.0 之前,Go 就已经在标准库中包含了对 JSON 的支持。 15 年前,我们第一次写了一篇关于 Go 对 JSON 的支持的文章!随着时间的推移,包会随着用户的需求而发展,encoding/json 也不例外。去年,我们写了一个新的 JSON 实验性 API,旨在带来期待已久的改进和修复。经过额外的反馈和完善,新的encoding/json/v2和encoding/json/jsontext包已经稳定并在Go 1.27中普遍可用!这篇文章是介绍实验、描述编码/json的问题以及新包介绍的文章的更新版本。 coding/json 的问题 总体而言,encoding/json 表现良好。使用 JSON 中的一些默认表示来编组和解编任意 Go 类型的想法,再加上自定义表示的能力,已被证明是高度灵活的。然而,自推出以来的几年里,各种用户都发现了许多缺点。行为缺陷encoding/json 中存在各种行为缺陷: JSON 语法处理不精确:多年来,JSON 的标准化程度不断提高,以便程序能够正确通信。一般来说,解码器在拒绝不明确的输入方面变得更加严格,以减少两个实现对特定 JSON 值有不同(成功)解释的机会。 coding/json 目前接受无效的 UTF-8,而最新的互联网标准 (RFC 8259) 需要有效的 UTF-8。默认行为应该在存在无效 UTF-8 的情况下报告错误,而不是引入静默数据损坏,这可能会导致下游出现问题。 coding/json 目前接受具有重复成员名称的对象。 RFC 8259 没有指定如何处理重复名称,因此实现可以自由选择任意值、合并值、丢弃值或报告错误。重复名称的存在会导致 JSON 值没有普遍认可的含义。这可能会被安全应用程序中的攻击者利用,并且之前已经被利用过(如 CVE-2017-12635 中)。默认行为应该在安全方面犯错误并拒绝重复的名称。切片和映射的 nilness 泄漏:JSON 通常用于与使用 JSON 实现的程序进行通信,该实现不允许将 null 解组为预期为 JSON 数组或对象的数据类型。由于encoding/json 将 nil 切片或映射编组为 JSON null ,因此在通过其他实现解组时可能会导致错误。一项调查表明,大多数 Go 用户更喜欢默认将 nil 切片和映射编组为空 JSON 数组或对象。不区分大小写的解组:解组时,使用不区分大小写的匹配将 JSON 对象成员名称解析为 Go 结构体字段名称。这是一个令人惊讶的默认值、一个潜在的安全漏洞和一个性能限制。方法调用不一致:由于实现细节,在指针接收器上声明的 MarshalJSON 方法由编码/json 调用不一致。虽然这被视为一个错误,但无法修复,因为太多应用程序依赖于当前行为。 API 缺陷 Encoding/json 的 API 可能很棘手或有限制:很难从 io.Reader 正确解组。用户经常编写 json.NewDecoder(r).Decode(v) ,它无法拒绝输入末尾的尾随垃圾。可以在编码器和解码器类型上设置选项,但不能与 Marshal 和 Unmarshal 函数一起使用。同样,实现 Marshaler 和 Unmarshaler 接口的类型无法使用这些选项,并且无法在调用堆栈中查找选项。例如,调用自定义 UnmarshalJSON 方法时,Decoder.DisallowUnknownFields 选项将失去作用。 Compact 、 Indent 和 HTMLEscape 函数写入 bytes.Buffer 而不是更灵活的东西,如 []byte 或 io.Writer 。这限制了这些功能的可用性。性能限制 抛开内部实现细节不谈,公共 API 会使其受到某些性能限制: MarshalJSON :MarshalJSON 接口方法强制实现分配返回的 []byte 。此外,语义要求encoding/json 验证结果是否是有效的JSON,并重新格式化以匹配指定的缩进。 UnmarshalJSON :UnmarshalJSON 接口方法要求提供完整的 JSON 值(没有任何尾随数据)。这会强制en​​coding/json解析要整体解组的JSON值,以确定它在调用Unmar之前的结束位置
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱