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

Swift JSON解码时API返回USER_LIST字段类型不一致如何处理

解码失败原因
  1. USER_LIST字段类型不固定:DATA_NUM为"0"时返回空字符串,与模型定义的[UserInfo]?类型不匹配
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:48:03