---
title: "Go 1.27 正式引入 encoding/json/v2，預設拒絕重複欄位與無效 UTF-8"
url: https://sammy.hk/go-1-27-json-v2/
author: Ethan
published: 2026-11-07T15:43:00+08:00
modified: 2026-11-07T09:55:11+08:00
description: "Go 語言團隊於 2026 年 11 月 4 日在官方部落格宣佈，encoding/json/v2 與 encoding/json/jsontext 兩個新套件已告穩定，並隨 Go 1.27 正式提供 [1]。這套 API 改動了沿用超過十五年的 JSON 序列化預設行為：解碼時遇到無效 UTF-8 或重複的物件欄位名…"
categories: ["開放源碼"]
tags: [Go, JSON, "程式語言", "開發工具"]
source: https://sammy.hk
---
![Go 1.27 encoding/json/v2 預設拒絕重複欄位與無效 UTF-8](https://sammy.hk/wp-content/uploads/2026/11/og-image-35755.jpg)Go 語言團隊於 2026 年 11 月 4 日在官方部落格宣佈，`encoding/json/v2` 與 `encoding/json/jsontext` 兩個新套件已告穩定，並隨 Go 1.27 正式提供 \[1\]。這套 API 改動了沿用超過十五年的 JSON 序列化預設行為：解碼時遇到無效 UTF-8 或重複的物件欄位名會直接報錯，指標為 nil 的切片與映射則改為輸出空陣列與空物件。官方同時指出，`v2` 的解碼效能最高可比舊版快十倍。

## 為何另開一個 v2 命名空間

Go 自 1.0 之前已在標準庫支援 JSON，`encoding/json` 的設計以反射為基礎，讓任意 Go 型別可以帶預設表示，並容許自訂。多年來社群指出不少缺陷，但部分問題與現有 API 綁得太緊，在 Go 1 相容承諾之下難以直接修正。

官方列出的行為問題包括：接受無效 UTF-8、接受重複欄位名、大小寫不敏感的欄位匹配，以及指標接收者的 `MarshalJSON` 方法呼叫不一致。最後一項雖然被視為錯誤，但由於太多應用依賴現況，已經無法更改。與其在同一套件內開出 `MarshalV2` 之類的平行命名，團隊選擇另立 `encoding/json/v2`，讓新行為可以在獨立命名空間中定義。

新結構將語法與語意分開。`jsontext` 只負責 JSON 文法層面的編碼與解碼，不依賴反射，並以串流方式運作；`v2` 則建立於其上，負責 Go 值與 JSON 之間的對應 \[2\]。`RawMessage` 現已成為 `jsontext.Value` 的型別別名。

## 預設行為的實際差異

從 `v1` 直接遷移到 `v2`，大部分用法仍然相似，但以下幾項預設會令既有程式出現新錯誤，值得在升級前逐一檢查。

第一，`v2` 遇到無效 UTF-8 會報錯，而舊版會默默接受，可能在 downstream 造成資料損壞。第二，物件出現重複欄位名時會報錯；官方特別提到，重複名稱在 RFC 8259 中並無一致解釋，歷史上曾被利用作攻擊，例如 CVE-2017-12635。第三，`nil` 切片與映射會序列化為 `[]` 與 `{}`，不再輸出 `null`。第四，解碼時欄位名稱改為大小寫敏感匹配。

此外，`omitempty` 的語意被重新定義：只有當欄位會編碼成 `null`、空字串、空陣列或空物件時才省略。`time.Duration` 因缺乏公認的預設表示，直接序列化會報錯，需由呼叫方以選項指定格式。官方表示，大部分行為差異都提供 struct tag 或呼叫層級選項，可切換回 `v1` 語意。

## 選項、串流與升級注意

`v2` 的 `Marshal` 與 `Unmarshal` 接受可變選項，解決了舊版只有 `Encoder`、`Decoder` 才能設定選項的限制。新增的 `MarshalWrite` 與 `UnmarshalRead` 可直接對 `io.Writer` 及 `io.Reader` 運作，避免為了讀寫而臨時建立編碼器。

自訂型別方面，除沿用 `Marshaler` 與 `Unmarshaler`，亦新增 `MarshalerTo` 與 `UnmarshalerFrom`，讓實作可以透過 `jsontext.Encoder` 或 `Decoder` 以串流方式處理，並把選項沿呼叫堆疊傳遞。官方指出，若要取得更明顯的效能提升，現有的自訂方法應一併遷移至新介面；單就解碼而言，基準測試顯示改善可達十倍。

這個項目由 2020 年底開始構思，2025 年在 Go 1.25 以實驗形式開放，最終於 1.27 轉為穩定。官方強調，大部分開發與推動工作由非 Google 僱員完成。對香港的 Go 服務團隊而言，短期內不宜全面替換所有 `encoding/json` 匯入；應先針對公開 API 的輸入驗證路徑試行，因重複欄位與 UTF-8 檢查正是最可能引發行為改變的地方，並參考官方遷移指南逐項調整 \[3\]。

## 參考資料

\[1\] [A new Go API for JSON（2026-11-04）](https://go.dev/blog/jsonv2)

\[2\] [encoding/json/v2 套件文件](https://go.dev/pkg/encoding/json/v2)

\[3\] [encoding/json/v2 遷移指南](https://go.dev/doc/jsonv2-migration)

### 相關文章：

1. [Go 1.27 正式提供 encoding/json/v2 反序列化效能最多快十倍](https://sammy.hk/go-json-v2-api/ "Go 1.27 正式提供 encoding/json/v2　反序列化效能最多快十倍")
2. [Go 1.27 正式推出 encoding/json/v2 標準庫 JSON API 大幅改版](https://sammy.hk/go-json-v2-stable/ "Go 1.27 正式推出 encoding/json/v2 標準庫 JSON API 大幅改版")
3. [Go 推出平台無關 SIMD 實驗：寫一次、跨架構加速](https://sammy.hk/go-%e6%8e%a8%e5%87%ba%e5%b9%b3%e5%8f%b0%e7%84%a1%e9%97%9c-simd-%e5%af%a6%e9%a9%97%ef%bc%9a%e5%af%ab%e4%b8%80%e6%ac%a1%e3%80%81%e8%b7%a8%e6%9e%b6%e6%a7%8b%e5%8a%a0%e9%80%9f/ "Go 推出平台無關 SIMD 實驗：寫一次、跨架構加速")
4. [Zig 0.17 發布：建置系統重新設計，增量編譯預期全面可用](https://sammy.hk/zig-0-17-%e7%99%bc%e5%b8%83%ef%bc%9a%e5%bb%ba%e7%bd%ae%e7%b3%bb%e7%b5%b1%e9%87%8d%e6%96%b0%e8%a8%ad%e8%a8%88%ef%bc%8c%e5%a2%9e%e9%87%8f%e7%b7%a8%e8%ad%af%e9%a0%90%e6%9c%9f%e5%85%a8%e9%9d%a2%e5%8f%af/ "Zig 0.17 發布：建置系統重新設計，增量編譯預期全面可用")
