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

如何处理带分页的第三方API条件式JSON响应

问题描述

调用某第三方API,其返回JSON结构如下:

{
  "data": [
    {
      "id": 111,
      "highPriorityItems": [
        {
          "time": "2022-01-01T00:00:50Z",
          "price": 5000.55
        },
        {
          "time": "2022-01-02T13:00:50Z",
          "price": 5600.55
        }
      ],
      "lowPriorityItems": [
        {
          "time": "2022-03-01T00:12:50Z",
          "price": 9000.55
        },
        {
          "time": "2022-03-02T22:00:50Z",
          "price": 6700.55
        }
      ]
    }
  ]
}

其中lowPriorityItems字段始终存在,highPriorityItems为可选字段,需优先保留该字段数据。

该API支持分页,同一id的lowPriorityItems和highPriorityItems可能分布在不同分页响应中。最终需要每个id对应一个合并两类数据切片的struct,后续可根据highPriorityItems是否为空选择使用对应数据。

现有Go代码框架如下,但不确定合并逻辑用遍历检查id还是map更高效:

package main

type Payload struct {
    Data []Entity `json:"data"`
}

type Entity struct {
    Id string `json:"id"`
    HighPriorityItems []Item `json:"highPriorityItems"`
    LowPriorityItems []Item `json:"lowPriorityItems"`
}

type Item struct {
    time string
    price float64
}

func main() {
    payloads := []&Payload{}
    
    for _, req := range requests {
        // 将响应反序列化为Payload结构体并追加到payloads切片
        // payloads = append(payloads, payload)
    }    

    // 此处需实现合并逻辑:合并相同id的Entity数据切片
}
解决方案

使用map实现高效合并是最优选择:遍历查找相同id的时间复杂度是O(n²),而map的键值对查找时间复杂度为O(1),在分页数据量较大时效率差距明显。

具体实现步骤

  1. 定义map[string]*Entity作为合并容器,key为Entity的Id,value为指向合并后Entity的指针
  2. 遍历所有分页返回的Payload,逐个处理其中的Entity:
    • 若map中无该id的Entity,初始化一个新Entity存入map(注意初始化切片避免nil)
    • 若map中已有该id的Entity,将当前Entity的HighPriorityItems和LowPriorityItems追加到已有Entity的对应切片中
  3. 最后将map中的值转换为切片,得到最终合并结果

修正后的完整代码

注意:原代码中Item的字段为小写,JSON反序列化会失败,需改为大写开头的导出字段:

package main

import "encoding/json"

type Payload struct {
    Data []Entity `json:"data"`
}

type Entity struct {
    Id                string `json:"id"`
    HighPriorityItems []Item `json:"highPriorityItems"`
    LowPriorityItems  []Item `json:"lowPriorityItems"`
}

type Item struct {
    Time  string  `json:"time"`
    Price float64 `json:"price"`
}

func main() {
    payloads := []*Payload{}
    // 假设requests是已定义的请求列表,此处省略请求及反序列化逻辑

    // 初始化合并用的map
    entityMap := make(map[string]*Entity)

    for _, payload := range payloads {
        for _, entity := range payload.Data {
            // 复制当前entity的id,避免循环变量引用问题
            id := entity.Id
            existingEntity, exists := entityMap[id]
            if !exists {
                // 初始化新的Entity,确保切片不为nil
                newEntity := Entity{
                    Id:                id,
                    HighPriorityItems: make([]Item, 0, len(entity.HighPriorityItems)),
                    LowPriorityItems:  make([]Item, 0, len(entity.LowPriorityItems)),
                }
                newEntity.HighPriorityItems = append(newEntity.HighPriorityItems, entity.HighPriorityItems...)
                newEntity.LowPriorityItems = append(newEntity.LowPriorityItems, entity.LowPriorityItems...)
                entityMap[id] = &newEntity
            } else {
                // 追加数据到已有Entity
                existingEntity.HighPriorityItems = append(existingEntity.HighPriorityItems, entity.HighPriorityItems...)
                existingEntity.LowPriorityItems = append(existingEntity.LowPriorityItems, entity.LowPriorityItems...)
            }
        }
    }

    // 将map转换为切片,方便后续使用
    mergedEntities := make([]Entity, 0, len(entityMap))
    for _, entity := range entityMap {
        mergedEntities = append(mergedEntities, *entity)
    }

    // 后续可根据mergedEntities处理业务逻辑
}

关键注意点

  • 处理循环变量引用:在遍历payload.Data时,需复制entity.Id,避免后续循环中变量被覆盖导致的错误
  • 初始化切片:提前初始化切片并设置容量,可减少内存分配次数,提升性能
  • 字段导出:Go中只有大写开头的字段才能被JSON包序列化/反序列化,必须修正Item的字段名

内容的提问来源于stack exchange,提问作者Coldchain9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:42:42