
Go 标准库 encoding/json 不支持 JSON 注释,需借助 JSON5 或 HJSON 等兼容注释的格式及其第三方 Go 实现来正确解析含 // 或 /* */ 注释的配置文件。
go 标准库 `encoding/json` 不支持 json 注释,需借助 json5 或 hjson 等兼容注释的格式及其第三方 go 实现来正确解析含 `//` 或 `/* */` 注释的配置文件。
JSON 规范(RFC 7159)明确禁止注释,因此 Go 内置的 json.Unmarshal 在遇到 // 或 /* */ 时会立即报错,例如 invalid character '/' looking for beginning of value。若需保留配置文件中的注释以提升可维护性(如标注备用地址、说明端口范围或临时禁用节点),必须切换至支持注释的 JSON 超集格式。
目前主流的两类兼容方案是 JSON5 和 HJSON:
- JSON5:扩展了 JSON 语法,支持单行 //、多行 /* */ 注释、末尾逗号、单引号字符串、无引号键名等,语义更接近 JavaScript 对象字面量;
- HJSON:专为人类编辑设计,语法更宽松(如允许省略引号、支持行内注释、换行分隔),但解析器实现相对较少。
✅ 推荐实践:使用 yosuke-furukawa/json5
安装:
go get github.com/yosuke-furukawa/json5
解析示例:
package main
import (
"fmt"
"log"
"github.com/yosuke-furukawa/json5"
)
type Config struct {
Tyo struct {
PingOnly bool `json:"ping_only"`
Addresses []string `json:"addresses"`
} `json:"tyo"`
Vie struct {
Addresses []string `json:"addresses"`
} `json:"vie"`
}
func main() {
data := []byte(`{
"tyo": {
"ping_only": true,
"addresses": [
//"155.133.245.25:27015-27050",
//"155.133.245.26:27015-27050",
"45.121.186.20:27015-27016",
"45.121.186.21:27015-27016"
]
},
"vie": {
"addresses": [
"185.25.182.225:27015-27050",
"185.25.182.226:27015-27050"
]
}
}`)
var cfg Config
if err := json5.Unmarshal(data, &cfg); err != nil {
log.Fatal("JSON5 parse error:", err)
}
fmt.Printf("TyO addresses: %+v\n", cfg.Tyo.Addresses)
fmt.Printf("Vie addresses: %+v\n", cfg.Vie.Addresses)
}
⚠️ 注意事项
- 安全性:JSON5/HJSON 解析器非标准库,需审查依赖来源与维护活跃度(推荐选用 Star 数高、有 CI/CD 和测试覆盖的项目);
- 性能开销:相比原生 encoding/json,解析速度略低(通常可忽略,除非高频解析超大文件);
- 工具链兼容性:编辑器/IDE 可能不原生支持 JSON5 语法高亮或校验,建议配合 .json5 后缀及对应插件;
- 生产环境建议:开发与测试阶段使用带注释的 JSON5 配置,CI/CD 流水线中可增加一步预处理(如用 json5 CLI 转为标准 JSON)供严格环境加载。
总之,当团队协作中需要可读性强、便于临时开关配置项的 JSON 文件时,采用 JSON5 是兼顾规范性与实用性的最佳选择。











