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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:27:03