Go语言REST API合并三个JSON数据失败求助
问题排查与解决方案
核心问题分析
返回的JSON缺失字段,本质是Go结构体字段的可见性与JSON序列化规则不匹配,同时存在结构体标签错误、变量复用导致的数据异常问题:
- Go语言中,只有首字母大写的结构体字段才会被
json.Marshal导出(小写字段属于包私有,无法被外部序列化工具访问) - 结构体字段名与期望的JSON键名不对应,需要通过
json标签指定映射关系 - 循环中复用变量未重新初始化,可能导致数据覆盖或重复
修正步骤与代码实现
1. 修正结构体定义(关键)
调整字段可见性并添加正确的JSON标签,确保序列化时能生成目标结构:
// 对应domain的detail项 type StrDomainInto struct { Domain string `json:"domain"` Element string `json:"element"` } // 对应单个field节点 type StrColumnInfo struct { Field string `json:"field"` Type string `json:"type"` Detail []StrDomainInto `json:"detail"` // 原小写domain改为大写Detail,标签映射到detail } // 最终合并后的根结构 type StrTable struct { Table string `json:"table"` TableType string `json:"table_type"` // 标签映射到table_type Field []StrColumnInfo `json:"field"` // 原小写column改为大写Field,标签映射到field }
2. 修正数据合并逻辑(避免变量复用问题)
在循环内部重新初始化临时变量,防止旧数据残留:
var mixData []StrTable for _, dataTable := range str_data_table { // 每次循环初始化新的StrTable实例 wMixData := StrTable{ Table: dataTable.Table, TableType: dataTable.TableType, } for _, dataColumn := range str_all_col { if dataTable.Table != dataColumn.Table { continue } // 每次循环初始化新的StrColumnInfo实例 wCol := StrColumnInfo{ Field: dataColumn.Field, Type: dataColumn.Type, } for _, dataDomain := range str_all_domain { if dataColumn.Field != dataDomain.Field { continue } // 直接构造StrDomainInto并添加,无需复用变量 wCol.Detail = append(wCol.Detail, StrDomainInto{ Domain: dataDomain.Domain, Element: dataDomain.Element, }) } wMixData.Field = append(wMixData.Field, wCol) } mixData = append(mixData, wMixData) } respondWithJSON(w, 200, mixData)
3. 修正respondWithJSON函数的状态码问题
原函数固定返回200,应使用传入的code参数:
func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { data, err := json.Marshal(payload) if err != nil { log.Printf("Failed to marshal JSON response : %v", payload) w.WriteHeader(500) return } w.Header().Add("Content-Type", "application/json") w.WriteHeader(code) // 改为传入的code,而非固定200 w.Write(data) }
验证结果
修正后序列化得到的JSON将完全符合预期结构:
{ "table": "tablea", "table_type": "pubilc", "field": [ { "field": "name", "type": "string", "detail": [ { "domain": "xxx", "element": "jjjjj" }, { "domain": "yyyy", "element": "ssss" } ] }, { "field": "surname", "type": "string", "detail": [ { "domain": "aaaaaa", "element": "dddd" }, { "domain": "bbbbbb", "element": "eeee" } ] } ] }
内容的提问来源于stack exchange,提问作者cyber_g
相关产品推荐
相关产品推荐

