Golang扫描数据库多行记录将关联数据合并为嵌套JSON数组问题
你遇到的问题本质是SQL内连接返回的是扁平化的笛卡尔积结果,仅修改结构体无法实现聚合效果,需要配合代码层面的分组逻辑,具体实现如下:
实现方案
第一步:调整结构体定义
先修正原有结构体的标签错误,同时定义符合输出格式的新结构体:
// 修正原有结构体的标签错误 type A struct { AID int64 `json:"aid"` Name string `json:"name"` Des string `json:"description"` // 对齐实际输出的description字段名 Price string `json:"price"` } type B struct { BID int64 `json:"bid"` Answer string `json:"answer"` // 修正原标签多写的冒号错误 Score int16 `json:"score"` } // 定义合并了section信息的B子项结构体 type BItem struct { B // 嵌入原有B结构体,复用字段 SecID int64 `json:"section_id"` SecName string `json:"section_name"` } // 定义最终输出的结构体 type Result struct { A A `json:"a"` B []BItem `json:"b"` // B改为数组类型,存储所有关联子项 }
第二步:修改数据扫描与聚合逻辑
新增map作为临时存储,按A的aid做分组聚合,避免A字段重复:
// 用map做临时聚合,key是A的aid,value是对应的Result对象 resMap := make(map[int64]Result) rows, err := db.Query(sqlStatement, RequestBody.tID) if err != nil { // 自行处理查询错误 } defer rows.Close() for rows.Next() { var a A var b B var secID int64 var secName string // 修正原代码重复扫描A.Price的错误,按SQL返回字段顺序对应扫描 err = rows.Scan(&a.AID, &a.Name, &a.Des, &a.Price, &b.BID, &b.Answer, &b.Score, &secID, &secName) if err != nil { // 自行处理扫描错误 } // 构造当前行的B子项 item := BItem{ B: b, SecID: secID, SecName: secName, } // 按aid分组聚合 if res, ok := resMap[a.AID]; ok { // 已存在同aid的记录,追加B子项 res.B = append(res.B, item) resMap[a.AID] = res } else { // 不存在同aid的记录,新建Result对象 resMap[a.AID] = Result{ A: a, B: []BItem{item}, } } } // 将map转为切片,得到最终输出格式 var results []Result for _, res := range resMap { results = append(results, res) }
注意事项
- 扫描字段的顺序必须和SQL查询返回的字段顺序完全一致,若你的SQL字段顺序和示例不同需要自行调整
- 若需要对最终结果按A的字段排序,可在map转切片的步骤增加排序逻辑
内容的提问来源于stack exchange,提问作者aakash singh
相关产品推荐
相关产品推荐

