如何全局配置Go GORM模型结构体自动以camelCase输出JSON
解决方案
方式1:使用jsoniter库(推荐,全局生效)
jsoniter是一款高性能Go JSON库,支持直接全局配置键名命名策略,既能自动转换字段名为lowerCamelCase,又会优先保留自定义json标签的设置,完美匹配需求。
- 安装依赖:
go get github.com/json-iterator/go
- 在项目初始化阶段配置全局JSON编码器:
import "github.com/json-iterator/go" // 全局配置JSON编码器,指定lowerCamelCase命名策略 var json = jsoniter.Config{ TagKey: "json", TagNamingStrategy: jsoniter.LowerCaseCamelCase, // 核心配置:自动转小驼峰 EscapeHTML: true, SortMapKeys: true, DisallowUnknownFields: false, }.Froze()
- 使用自定义的
json变量序列化结构体:
// 从GORM查询数据后,用全局配置的编码器序列化 bytes, err := json.Marshal(data) if err != nil { // 处理错误逻辑 } // bytes即为符合要求的camelCase格式JSON
方式2:自定义JSON编码器(适用于Web框架场景)
如果项目基于Gin、Beego这类Web框架,可以在框架层面替换默认JSON编码器,实现全局字段名转换。以Gin为例:
- 安装
strcase工具包(用于字段名大小写转换):
go get github.com/iancoleman/strcase
- 自定义Gin的JSON渲染器:
import ( "github.com/gin-gonic/gin" "github.com/iancoleman/strcase" "encoding/json" "reflect" ) // 自定义JSON编码器,将结构体字段名转为lowerCamelCase func CamelCaseJSONMarshal(v interface{}) ([]byte, error) { val := reflect.ValueOf(v) typ := reflect.TypeOf(v) result := make(map[string]interface{}) for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) fieldVal := val.Field(i).Interface() // 优先使用json标签 jsonTag := field.Tag.Get("json") if jsonTag != "" && jsonTag != "-" { result[jsonTag] = fieldVal continue } // 转换字段名为lowerCamelCase camelName := strcase.ToLowerCamel(field.Name) result[camelName] = fieldVal } return json.MarshalIndent(result, "", " ") } // 在Gin初始化时设置自定义JSON渲染 func main() { r := gin.Default() r.Use(func(c *gin.Context) { c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8") c.JSON = func(code int, obj interface{}) { data, err := CamelCaseJSONMarshal(obj) if err != nil { c.AbortWithError(500, err) return } c.Writer.WriteHeader(code) c.Writer.Write(data) } }) // 后续路由处理直接返回结构体即可自动转camelCase }
方式3:基础结构体嵌入(无第三方库)
如果不想引入外部依赖,可以创建带MarshalJSON方法的基础结构体,让所有模型嵌入它实现字段名自动转换:
- 定义基础结构体并实现序列化方法:
import ( "encoding/json" "reflect" "strings" ) type BaseModel struct{} func (b BaseModel) MarshalJSON() ([]byte, error) { t := reflect.TypeOf(b) v := reflect.ValueOf(b) output := make(map[string]interface{}) // 遍历当前结构体字段 for i := 0; i < t.NumField(); i++ { field := t.Field(i) val := v.Field(i).Interface() // 优先读取json标签 jsonTag := field.Tag.Get("json") if jsonTag != "" && jsonTag != "-" { output[jsonTag] = val continue } // 转lowerCamelCase:首字母小写,其余不变 camelName := strings.ToLower(field.Name[:1]) + field.Name[1:] output[camelName] = val } // 处理嵌入的其他匿名结构体字段 if t.NumField() > 0 && t.Field(0).Anonymous { embeddedVal := v.Field(0).Interface() embeddedBytes, err := json.Marshal(embeddedVal) if err != nil { return nil, err } var embeddedMap map[string]interface{} json.Unmarshal(embeddedBytes, &embeddedMap) for k, val := range embeddedMap { output[k] = val } } return json.Marshal(output) }
- 让模型结构体嵌入
BaseModel:
type Job struct { BaseModel ID uint Title string JobContent string `json:"jobContent"` }
调用json.Marshal(data)时,会自动应用字段名转换规则。
内容的提问来源于stack exchange,提问作者Charas
相关产品推荐
相关产品推荐

