Swift JSON解码时API返回USER_LIST字段类型不一致如何处理
解码失败原因
- USER_LIST字段类型不固定:
DATA_NUM为"0"时返回空字符串,与模型定义的[UserInfo]?类型不匹配 DATA_NUM为"1"时数组中存在空字符串元素,无法直接解码为UserInfo类型
适配方案
通过自定义解码逻辑处理多类型字段,同时实现数组无效元素自动过滤,原有解码逻辑无需修改,完整实现代码如下:
方案1:自定义UserData解码逻辑
import Foundation struct UserDataResponse: Codable { let RESPONSE: UserData? } struct UserInfo: Codable { let USER_NAME: String? let USER_AGE: String? let ID: String? } struct UserData: Codable { let DATA_NUM: String? let USER_LIST: [UserInfo]? init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) DATA_NUM = try container.decodeIfPresent(String.self, forKey: .DATA_NUM) // 处理空字符串场景(DATA_NUM=0) if let _ = try? container.decodeIfPresent(String.self, forKey: .USER_LIST) { USER_LIST = [] return } // 处理数组场景,自动过滤无效元素 guard var arrayContainer = try? container.nestedUnkeyedContainer(forKey: .USER_LIST) else { USER_LIST = nil return } var tempList = [UserInfo]() while !arrayContainer.isAtEnd { if let user = try? arrayContainer.decode(UserInfo.self) { tempList.append(user) } else { // 跳过空字符串等无效元素 _ = try? arrayContainer.decode(String.self) } } USER_LIST = tempList } enum CodingKeys: String, CodingKey { case DATA_NUM, USER_LIST } }
方案2:属性包装器复用逻辑(推荐)
如果需要在多个模型中处理同类多类型字段,可以用属性包装器封装逻辑,简化代码:
// 通用属性包装器:自动适配空字符串/泛型数组,自动过滤数组无效元素 @propertyWrapper struct FlexibleList<T: Decodable>: Decodable { var wrappedValue: [T]? init(from decoder: Decoder) throws { // 空字符串场景处理 if let _ = try? decoder.singleValueContainer().decode(String.self) { wrappedValue = [] return } // 数组场景处理 guard var arrayContainer = try? decoder.unkeyedContainer() else { wrappedValue = nil return } var result = [T]() while !arrayContainer.isAtEnd { if let element = try? arrayContainer.decode(T.self) { result.append(element) } else { _ = try? arrayContainer.decode(String.self) } } wrappedValue = result } } // 模型定义仅需修改一行 struct UserData: Codable { let DATA_NUM: String? @FlexibleList<UserInfo> var USER_LIST: [UserInfo]? }
效果说明
两种方案都可以适配所有场景:
- DATA_NUM为"0"时,USER_LIST解码为空数组
- DATA_NUM为"1"时,自动过滤数组中的空字符串,仅保留合法UserInfo对象
- DATA_NUM为"2"时,正常解码所有UserInfo对象
原有解码代码无需任何修改即可正常运行。
内容的提问来源于stack exchange,提问作者akaakoz
相关产品推荐
相关产品推荐

