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
相关产品推荐
相关产品推荐

