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

Apollo iOS如何处理GraphQL响应的部分解码失败问题?

解决Apollo Swift数组部分解析失败的容错方案

一、用Apollo内置的数组解码容错配置

Apollo Swift 从0.50.0版本开始,支持让数组解码时自动跳过解析失败的元素,不用改太多代码就能实现需求。具体操作:

初始化ApolloClient的时候,给客户端配置里的解码器加上arrayDecodingHandling设置:

let client = ApolloClient(
    url: URL(string: "你的GraphQL接口地址")!,
    configuration: ApolloClient.Configuration(
        decoder: JSONDecoder().then {
            $0.arrayDecodingHandling = .ignoreFailedElements
        }
    )
)

这么设置后,所有数组类型的字段在解码时,只要单个元素解析失败,就自动跳过,不会连累整个数组甚至整个查询结果失败。

二、针对特定字段做自定义解码(更精准控制)

如果只需要给items数组加容错,或者需要更灵活的处理逻辑,可以自定义解码逻辑:

1. 写个方法处理单个Item的解码

给Apollo生成的GetCollectionsQuery.Data.GetCollections.Item类型加个扩展,让它解码失败时返回nil:

extension GetCollectionsQuery.Data.GetCollections.Item {
    static func decodeOrNil(from decoder: Decoder) -> Self? {
        do {
            return try Self(from: decoder)
        } catch {
            print("解析单个Item失败,直接跳过: \(error)")
            return nil
        }
    }
}

2. 重写数组字段的解码逻辑

再给GetCollectionsQuery.Data.GetCollections类型加扩展,重写items的解码逻辑,过滤掉解码失败的元素:

extension GetCollectionsQuery.Data.GetCollections: Decodable {
    enum CodingKeys: String, CodingKey {
        case items
        // 这里要把查询里的其他字段都列出来,比如你注释的other fields
        // ... 其他字段名
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 先解码其他字段,这里要把Apollo生成的其他字段解码逻辑原封不动抄过来
        // 比如如果有name字段,就写 self.name = try container.decode(String.self, forKey: .name)
        // ... 其他字段解码
        
        // 解码items数组,过滤掉失败的元素
        self.items = try container.decodeIfPresent([GetCollectionsQuery.Data.GetCollections.Item?].self, forKey: .items)?
            .compactMap { $0 } ?? []
    }
}

注意:这种方式要手动维护其他字段的解码代码,后续如果查询字段变了,这里也要同步更新,不然会漏解码。

三、临时改查询字段的可选性(应急用,不推荐)

如果不想折腾解码逻辑,也可以临时修改GraphQL查询,把出错的非空字段的!去掉,改成可选类型:

query mobile_getCollections() {
  getCollections() {
    // ... other fields

    items {
      activeRange {
        expires  // 原来的Int!改成Int
        starts   // 原来的Int!改成Int
      }
    }

  }
}

重新生成Swift代码后,就算后端返回错误格式,只会让expires或starts变成nil,不会导致整个Item或者数组解析失败。但这个方法会改变类型定义,可能影响业务逻辑,只能临时用用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:30:51