
Go 1.25 引入了新的实验性 JSON 包,包括 encoding/json/v2
与 encoding/json/jsontext
,旨在尝试解决当前 encoding/json
包的限制与长期争议。这两个包需要设置特殊的构建标志或标签才能启用,虽然目前仍处于实验阶段,但已经可供开发者在实际环境中测试。
新版 v2 在行为上更符合 RFC 8259 标准,最明显的差异是强制检查输入数据的正确性。当 JSON 包含无效 UTF-8 字符时,解码器会直接报告错误,而不是像旧版那样默默接受并可能导致数据损坏。同时,当对象出现重复的成员名称时,v2 会拒绝处理,避免因实现解读方式不同而产生安全风险。
在数据结构对应方面,v2 将区分大小写设为默认行为,JSON 字段名称需与 Go struct 字段精确匹配。此外,nil 的 slice 与 map 在序列化时会输出为空数组或空对象,减少跨语言解析时因 null 而无法正确识别为数组或对象的情况,使跨系统交换数据更稳定一致。这些行为均可通过选项进行调整,让开发者在新旧语义之间取得平衡。
架构与性能改进
此次改版采用双层架构,jsontext
专注于语法处理,提供真正的流式编码器与解码器,能够逐个读写 JSON 值或 Token。而 v2
则负责语义层,提供将 Go 数据结构转换为 JSON(Marshal)与将 JSON 还原为 Go 数据结构(Unmarshal)的功能,并将选项纳入一级参数,让开发者能直接控制行为。这样的设计改善了旧版解码器难以检查输入结尾噪声的问题,也避免了必须先整体缓冲再处理的低效流程。
除了保留既有的 Marshaler
与 Unmarshaler
接口外,v2 新增了 MarshalerTo
与 UnmarshalerFrom
,允许类型直接利用 jsontext
的编码器与解码器实现。这种方式避免了重复解析与额外分配,对于处理大型或嵌套结构的 JSON 特别有利。
向后兼容与过渡机制
Go 团队并未将 v1 与 v2 完全独立,在启用实验性 JSON 包时,v1 会改以 v2 的实现为底层。开发者无需修改代码即可测试,当功能符合预期即可逐步过渡到 v2,反之则仍可依赖既有的 v1 行为。
目前,v2 在序列化性能上大致与 v1 相当,而在反序列化方面则明显加速,可达数倍提升。官方强调,这些 API 仍属实验性质,未来可能调整甚至不被采用,但其实现质量已足以支撑大型项目运行,呼吁开发者通过实际测试反馈意见,协助决定后续发展方向。