
go 语言中 struct 字段的 json 和 bson 序列化默认采用 pascalcase 到 snake_case 或原样保留的策略,但无法全局修改默认行为;需通过结构体标签显式声明,或借助代码生成工具实现“零重复标签”的驼峰命名约定。
go 语言中 struct 字段的 json 和 bson 序列化默认采用 pascalcase 到 snake_case 或原样保留的策略,但无法全局修改默认行为;需通过结构体标签显式声明,或借助代码生成工具实现“零重复标签”的驼峰命名约定。
在 Go 中,json 和 bson 标签决定了结构体字段在序列化(如 json.Marshal 或 bson.Marshal)时使用的键名。默认情况下:
- json 包保持首字母大写不变(即 JdId → "JdId"),除非字段为小写字母开头(此时被忽略);
- bson 包(如 go.mongodb.org/mongo-driver/bson)默认将字段名转为全小写、无分隔符的 snake_case 形式(即 JdId → "jdid")。
但你期望的是统一使用 lowerCamelCase(如 JdId → "jdId"、AcceptTimestamp → "acceptTimestamp"),且不想为每个字段重复书写相同逻辑的标签——这很合理,尤其在大型项目中可显著提升可维护性。
遗憾的是:Go 语言标准库和主流驱动(如 encoding/json、go.mongodb.org/mongo-driver/bson)均不支持全局自定义字段名转换规则。json 和 bson 包均严格遵循标签优先原则:有标签则用标签,无标签则按默认规则推导(且该推导逻辑不可配置)。
✅ 正确做法是显式声明标签,并遵循一致的命名约定:
type CvJdRelationInfo struct {
JdId string `json:"jdId" bson:"jdId"`
CvId string `json:"cvId" bson:"cvId"`
Status int16 `json:"status" bson:"status"`
AcceptTimestamp int64 `json:"acceptTimestamp" bson:"acceptTimestamp"`
}
⚠️ 注意事项:
- bson 标签中 "acceptTimeStamp" 的拼写应与期望一致(注意 Time vs Timestamp);建议统一为 acceptTimestamp(标准 camelCase);
- 若使用 gopkg.in/mgo.v2(已归档),其 bson 行为略有不同(如自动下划线转换),请确认所用驱动版本;
- 错误示例:json:"status" + bson:"status" 是安全的,但 json:"Status" 会导致 JSON 输出为 "Status"(不符合 REST API 惯例),应避免。
? 进阶方案(免手动写标签): 可借助代码生成工具(如 stringer 思路延伸)或自定义 go:generate 脚本,基于结构体定义自动生成带规范标签的包装类型或修改后的源码。例如使用 github.com/freddierice/structtag 或编写简单 AST 分析器,将 JdId 自动映射为 jdId 并注入标签。
? 总结:Go 的序列化标签机制设计上强调显式优于隐式,因此“省略标签”仅适用于默认规则恰好匹配需求的场景。若需 lowerCamelCase,唯一健壮、可移植、无需依赖特殊运行时的方式,就是为每个导出字段添加标准化的 json 和 bson 标签——这是社区事实标准,也被 Swagger/OpenAPI、Gin、Echo 等框架广泛兼容。











