Go语言:Gorm关联结构体经Gin输出扁平化JSON的便捷方案咨询
解决方案:Go结构体JSON扁平化的便捷实现
方案1:反射实现通用扁平化工具函数
通过反射递归遍历结构体字段,自动将嵌套字段扁平化,生成map[string]interface{}后直接返回给Gin即可,无需手动映射每个字段。
import ( "reflect" "strings" ) // FlattenStruct 将结构体扁平化,嵌套字段的key自动拼接父字段前缀(优先使用json标签) func FlattenStruct(v interface{}) map[string]interface{} { result := make(map[string]interface{}) flatten(reflect.ValueOf(v), "", result) return result } func flatten(val reflect.Value, prefix string, result map[string]interface{}) { // 处理指针类型,自动解引用 for val.Kind() == reflect.Ptr { if val.IsNil() { return } val = val.Elem() } // 非结构体类型直接存入结果 if val.Kind() != reflect.Struct { if prefix != "" { result[prefix] = val.Interface() } return } typ := val.Type() for i := 0; i < val.NumField(); i++ { field := val.Field(i) fieldType := typ.Field(i) // 跳过未导出的私有字段 if fieldType.PkgPath != "" { continue } // 获取字段的json标签,无标签则用字段名;跳过json标签为"-"的字段 jsonTag := fieldType.Tag.Get("json") if jsonTag == "-" { continue } key := fieldType.Name if jsonTag != "" { key = strings.Split(jsonTag, ",")[0] } // 拼接前缀,生成扁平化后的key currentKey := key if prefix != "" { currentKey = prefix + "_" + key } flatten(field, currentKey, result) } }
使用方式:
在Gin接口中直接调用工具函数转换后返回:
func yourHandler(c *gin.Context) { var s Structure // 假设已从数据库查询填充s(包含嵌套结构体) flatData := FlattenStruct(s) c.JSON(http.StatusOK, flatData) }
方案2:自定义结构体JSON序列化
让主结构体实现json.Marshaler接口,内部复用扁平化逻辑,这样直接返回结构体时会自动生成扁平化JSON:
import "encoding/json" type Structure struct { Field1 string `json:"field1" gorm:"column:field1"` Field2 string `json:"field2" gorm:"column:field2"` EnotherStructure EnotherStructure `json:"-" gorm:"foreignKey:xxx"` // json标签设为"-",避免默认序列化嵌套结构 } func (s Structure) MarshalJSON() ([]byte, error) { flatMap := FlattenStruct(s) return json.Marshal(flatMap) }
使用方式:
直接返回结构体即可,Gin会自动调用自定义序列化逻辑:
func yourHandler(c *gin.Context) { var s Structure // 数据库查询填充s c.JSON(http.StatusOK, s) }
注意事项
- 工具函数支持多层嵌套结构体,比如
A.B.C.Field会自动转为a_b_c_field(若使用json标签则用标签名拼接) - 若需要自定义前缀规则(比如驼峰式),可修改
currentKey的拼接逻辑 - 如需处理切片、数组类型,可在
flatten函数中补充对应逻辑(默认会保留数组结构,不会展开元素)
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

