Swift中如何解码嵌套响应数据?需解析响应里的items字段
嘿,我来帮你搞定Swift里的JSON解码问题!咱们一步步来,先解决items字段的解析,再详细讲讲嵌套结构的解码方法。
首先我先模拟一套常见的代码场景(如果和你的实际情况有出入,你可以调整结构体字段或响应结构):
请求函数示例
func fetchCities(completion: @escaping (Result<[City], Error>) -> Void) { guard let url = URL(string: "https://your-api-endpoint.com/cities") else { completion(.failure(NSError(domain: "Invalid URL", code: -1, userInfo: nil))) return } URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { completion(.failure(error)) return } guard let data = data else { completion(.failure(NSError(domain: "No data received", code: -2, userInfo: nil))) return } // 这里就是你遇到解码问题的核心区域 do { // 原来的错误写法:直接解码成[City],但API返回的是包含items的顶层对象 let cities = try JSONDecoder().decode([City].self, from: data) completion(.success(cities)) } catch { completion(.failure(error)) print("解码失败:\(error)") } }.resume() }
City结构体示例
struct City: Codable { let id: Int let name: String let country: String }
典型API响应数据(包含items字段)
{
"status": "success",
"message": "Fetched cities successfully",
"items": [
{"id": 1, "name": "Tokyo", "country": "Japan"},
{"id": 2, "name": "Paris", "country": "France"}
]
}
问题本质是:API返回的根结构不是直接的[City]数组,而是一个包含items数组的顶层对象。所以我们需要先定义一个匹配顶层结构的响应结构体,再从中提取items数据。
步骤1:定义顶层响应结构体
// 完全匹配API返回的完整JSON结构 struct CityResponse: Codable { let status: String let message: String let items: [City] // 这里对应响应里的items字段,类型就是你的City数组 }
步骤2:修改解码逻辑
把原来的解码代码改成先解码顶层响应,再取出items:
do { let response = try JSONDecoder().decode(CityResponse.self, from: data) completion(.success(response.items)) // 直接返回items里的城市数组 } catch { completion(.failure(error)) print("解码失败:\(error)") }
这样就能正确解析出items字段里的城市数据了!
如果你的API响应有更深层次的嵌套(比如每个City里还有coordinates子对象),处理思路也很清晰:
示例嵌套响应数据
{
"items": [
{
"id": 1,
"name": "Tokyo",
"country": "Japan",
"coordinates": {
"latitude": 35.6762,
"longitude": 139.6503
}
}
]
}
步骤1:定义嵌套的子结构体
先给嵌套的coordinates单独定义一个符合Codable的结构体:
struct Coordinates: Codable { let latitude: Double let longitude: Double }
步骤2:修改City结构体,加入嵌套字段
直接把嵌套结构体作为City的一个字段即可:
struct City: Codable { let id: Int let name: String let country: String let coordinates: Coordinates // 嵌套的结构体字段 }
步骤3:正常解码即可
Codable协议会自动处理嵌套结构的编码和解码,只要你的结构体字段名和JSON键名完全匹配,直接用JSONDecoder解码就行,不需要额外操作。
特殊情况:字段名不匹配怎么办?
如果JSON里的键名和你Swift结构体的字段名不一致(比如JSON用lat,你想叫latitude),可以用CodingKeys自定义映射:
struct Coordinates: Codable { let latitude: Double let longitude: Double // 自定义编码/解码的键映射 enum CodingKeys: String, CodingKey { case latitude = "lat" case longitude = "lon" } }
如果还是解码失败,优先检查这几点:
- 字段名是否完全匹配:Swift默认是驼峰命名,JSON如果是蛇形命名,可以设置
JSONDecoder的keyDecodingStrategy = .convertFromSnakeCase自动转换 - 字段类型是否一致:比如JSON里是数字,你结构体里用了
String就会报错 - 是否有可选字段:如果JSON里某个字段可能不存在,要把结构体对应字段设为可选类型(比如
let name: String?)
举个自动转蛇形的例子:
let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase // 自动把snake_case转成camelCase let response = try decoder.decode(CityResponse.self, from: data)
内容的提问来源于stack exchange,提问作者Aidogdy Shahyrov

