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

Swift 如何将API响应结构体按相同id_category分组转换为自定义模型

实现步骤

1 先修正结构体定义的问题

你给出的结构体存在几处需要调整的点:

  • 原ProductDataResponse里的status属性定义为Int,但API返回的是字符串类型的"ok",需要修正类型
  • 解码用的Data结构体名和Swift内置的Foundation.Data重名,建议改名避免冲突
  • 你定义的ListCategory里的idCategory漏了类型声明,且结合预期输出,最终结构需要保留原始响应的公共字段(timestamp、status、message)

修正后的完整结构体如下:

import Foundation

// 原始API响应解码用结构体
struct ProductDataResponse: Decodable {
    let timestamp: Int
    let status: String
    let message: String
    let data: [ProductDataItem]
}

struct ProductDataItem: Decodable {
    let id: Int
    let idCategory: Int
    let products: [Product]
    
    enum CodingKeys: String, CodingKey {
        case id
        case idCategory = "id_category"
        case products
    }
}

struct Product: Codable {
    let id: Int
    let productName: String
    // 接口无返回此字段可设为可选或给默认值
    let idJelajah: Int?
    
    enum CodingKeys: String, CodingKey {
        case id
        case productName = "product_name"
        case idJelajah
    }
}

// 你需要的分组后目标结构体
struct GroupedCategoryResponse: Encodable {
    let timestamp: Int
    let status: String
    let message: String
    let data: [Category]
}

struct Category: Encodable {
    let idCategory: Int
    let products: [Product]
    
    enum CodingKeys: String, CodingKey {
        case idCategory = "id_category"
        case products
    }
}

2 核心分组转换逻辑

通过字典做临时存储,以idCategory为key,对应分类下的产品数组为value,遍历原始数据合并产品后转成目标结构即可,建议给原始响应结构体写扩展方法实现转换:

extension ProductDataResponse {
    func convertToGrouped() -> GroupedCategoryResponse {
        // 临时字典用于按分类ID聚合产品
        var categoryProductMap = [Int: [Product]]()
        
        // 遍历原始数据填充字典
        data.forEach { item in
            if categoryProductMap[item.idCategory] == nil {
                categoryProductMap[item.idCategory] = []
            }
            categoryProductMap[item.idCategory]?.append(contentsOf: item.products)
        }
        
        // 字典转成目标分类数组,可选按分类ID排序保证输出顺序稳定
        let categoryList = categoryProductMap
            .map { Category(idCategory: $0.key, products: $0.value) }
            .sorted { $0.idCategory < $1.idCategory }
        
        // 组装返回最终结果
        return GroupedCategoryResponse(
            timestamp: timestamp,
            status: status,
            message: message,
            data: categoryList
        )
    }
}

3 使用示例

解码原始API响应后直接调用转换方法即可得到你需要的结构:

// 假设apiData是接口返回的原始Data数据
let originalResponse = try JSONDecoder().decode(ProductDataResponse.self, from: apiData)
let groupedResponse = originalResponse.convertToGrouped()

// 如果需要转成JSON输出可以用以下代码
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let jsonData = try? encoder.encode(groupedResponse),
   let jsonStr = String(data: jsonData, encoding: .utf8) {
    print(jsonStr)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 10:15:02