跳轉到

ClosureBuilder Deterministic JSON Encoding

概念概覽

encoding/json 的不確定性來源

核心知識

encoding/json 的不確定性來源

Go 1.21+ 的 encoding/json 雖然對 map key 有排序保證,但以下兩點仍不可控: - float 格式1.0 vs 1 vs 1.000000,不同版本/平台可能不同 - time 格式time.Time 的序列化格式取決於 MarshalJSON 實作,可能含有 timezone offset 變化

若 ClosureBuilder 用這些值產生雜湊(如 bundle fingerprint),微小格式差異會導致相同語意的 config 產生不同 hash,觸發非預期的 content_mutation。

Custom JSON Encoder 的取捨

優點:
  - float 格式固定(如統一 strconv.FormatFloat(..., 'f', -1, 64))
  - time 格式固定(如統一 UTC RFC3339Nano)
  - map key 排序明確

缺點:
  - 需自行維護 encoder
  - 新增型別時需手動支援

對於 hash-based fingerprint 場景,deterministic 輸出比開發便利性更重要,custom encoder 是正確選擇。

經驗教訓

  • 任何用於產生 fingerprint/hash 的序列化都必須保證 deterministic,encoding/json 在 float 和 time 上不夠可靠

  • Custom encoder 的維護成本在早期容易低估,應在設計時即規劃好哪些型別需要支援

常見陷阱

  • 升級 Go 版本後 encoding/json 行為可能改變,造成既有 fingerprint 全部失效(需要強制重新 sync)

  • time.Time 若混用不同 timezone,即使語意相同也會產生不同序列化結果

最佳實踐

  • Fingerprint 用途的 JSON 序列化:float 統一用 strconv.FormatFloat,time 統一轉 UTC 後序列化

  • 為 custom encoder 寫 golden file 測試,確保 Go 版本升級後輸出不變

相關概念

來源 Sessions

日期 Session 貢獻摘要

| 2026-04-02 | 157b6880-f9d3-466a-abf9-07af0459b5d5 | 記錄了為何不用 encoding/json 而改用 custom encoder 來保證 deterministic hash 輸出 |


本概念頁面由 Semi-Brain Wiki 系統自動維護

最後更新: 2026-04-02