Go语言如何按rooms->code对JSON数组分组且不生成重复节点
问题场景
我目前使用Golang进行开发,相关JSON数据通过struct生成,现在需要基于rooms下的code字段的值对数据进行分组,按房间编码对数组分类,且不生成重复的JSON节点,合并相同房间编码下的rates数组内容。
原始JSON数据
{ "responseStatus": "SUCCESS", "version": "v1.9", "checkIn": "2021-10-12", "checkOut": "2021-10-16", "currency": "AED", "hotels": [ { "code": "OT000000001", "name": "TAJ TEST HOTEL", "rooms": [ { "code": "9011", "name": "Beach Villa With Jacuzzi", "rates": [ { "subSupplierId": "DC", "boardCode": "FB", "ratePlanCode": "9011_0_11_136_136", "channel": 23, "allotment": 100, "price": 1469.04, "cancellationPolicy": { "policies": null } } ] }, { "code": "8525", "name": "Doubello", "rates": [ { "subSupplierId": "DC", "boardCode": "FB", "ratePlanCode": "8525_0_11_136_136", "channel": 23, "allotment": 100, "price": 4407.08, "cancellationPolicy": { "policies": null } } ] }, { "code": "8525", "name": "Doubello", "rates": [ { "subSupplierId": "DC", "boardCode": "", "ratePlanCode": "8525_0_22_136_136", "channel": 23, "allotment": 100, "price": 7345.12, "cancellationPolicy": { "policies": null } } ] } ] } ], "remark": "" }
期望输出结果
{ "responseStatus": "SUCCESS", "version": "v1.9", "checkIn": "2021-10-12", "checkOut": "2021-10-16", "currency": "AED", "hotels": [ { "code": "OT000000001", "name": "TAJ TEST HOTEL", "rooms": [ { "code": "9011", "name": "Beach Villa With Jacuzzi", "rates": [ { "subSupplierId": "DC", "boardCode": "FB", "ratePlanCode": "9011_0_11_136_136", "channel": 23, "allotment": 100, "price": 1469.04, "cancellationPolicy": { "policies": null } } ] }, { "code": "8525", "name": "Doubello", "rates": [ { "subSupplierId": "DC", "boardCode": "FB", "ratePlanCode": "8525_0_11_136_136", "channel": 23, "allotment": 100, "price": 4407.08, "cancellationPolicy": { "policies": null } }, { "subSupplierId": "DC", "boardCode": "", "ratePlanCode": "8525_0_22_136_136", "channel": 23, "allotment": 100, "price": 7345.12, "cancellationPolicy": { "policies": null } } ] } ] } ], "remark": "" }
实现方案(Golang代码)
先定义对应结构的结构体,用map做临时存储对房间code去重,遍历过程中合并相同code房间的rates数组,最后将map转为数组替换原rooms字段即可:
package main import ( "encoding/json" "fmt" ) type CancellationPolicy struct { Policies interface{} `json:"policies"` } type Rate struct { SubSupplierId string `json:"subSupplierId"` BoardCode string `json:"boardCode"` RatePlanCode string `json:"ratePlanCode"` Channel int `json:"channel"` Allotment int `json:"allotment"` Price float64 `json:"price"` CancellationPolicy CancellationPolicy `json:"cancellationPolicy"` } type Room struct { Code string `json:"code"` Name string `json:"name"` Rates []Rate `json:"rates"` } type Hotel struct { Code string `json:"code"` Name string `json:"name"` Rooms []Room `json:"rooms"` } type Response struct { ResponseStatus string `json:"responseStatus"` Version string `json:"version"` CheckIn string `json:"checkIn"` CheckOut string `json:"checkOut"` Currency string `json:"currency"` Hotels []Hotel `json:"hotels"` Remark string `json:"remark"` } func main() { // 替换为实际的原始JSON数据 rawJson := `上面的原始JSON字符串` var resp Response err := json.Unmarshal([]byte(rawJson), &resp) if err != nil { panic(err) } // 逐个处理每个酒店的房间合并逻辑 for hotelIdx := range resp.Hotels { hotel := &resp.Hotels[hotelIdx] roomMap := make(map[string]Room) for _, room := range hotel.Rooms { if existRoom, ok := roomMap[room.Code]; ok { // 已存在同编码房间,合并rates existRoom.Rates = append(existRoom.Rates, room.Rates...) roomMap[room.Code] = existRoom } else { roomMap[room.Code] = room } } // map转回数组覆盖原rooms mergedRooms := make([]Room, 0, len(roomMap)) for _, room := range roomMap { mergedRooms = append(mergedRooms, room) } hotel.Rooms = mergedRooms } // 输出格式化后的结果 result, err := json.MarshalIndent(resp, "", " ") if err != nil { panic(err) } fmt.Println(string(result)) }
注意事项
- 如果需要保留房间原始的出现顺序,可以额外新增一个切片存储code的出现顺序,最后按顺序从map中取值组装rooms数组即可,上述代码默认不保证顺序。
- 若业务场景中存在同code的房间name不一致的情况,可自行调整逻辑选择保留第一个name或者最新的name。
内容的提问来源于stack exchange,提问作者sunil
相关产品推荐
相关产品推荐

