You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:33:37