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

构建Airtable API返回JSON的Swift Codable模型时fields部分卡壳求助

解决Airtable API返回数据的Swift Codable模型编写问题

首先纠正你当前Record结构体的id问题:你用UUID()作为默认id,但Airtable API返回的id是字符串类型(如"recBOdydIpM2P3xkZ"),且Identifiable协议的id支持任意Hashable类型,所以需要把id改成String类型并移除默认值,让它从JSON中解码。

接下来处理fields部分:需要创建独立的Fields结构体对应JSON中的fields对象,由于JSON键包含空格、特殊字符(如% GP)不符合Swift命名规范,需通过CodingKeys枚举做键名映射。

完整模型代码

import Foundation

struct Record: Codable, Identifiable {
    let id: String // 对应API返回的字符串id
    let createdTime: Date
    let fields: Fields
}

struct Fields: Codable {
    let gpPercentage: String
    let totalRx: Int
    let grossProfit: Double
    let totalReceived: Double
    let date: String // 若需转为Date类型,可自定义解码逻辑
    let copay: Double
    let acquisitionCost: Double
    let averageGP: Double
    let tpRemitted: Double
    
    // 映射JSON中的特殊键名到Swift规范命名
    enum CodingKeys: String, CodingKey {
        case gpPercentage = "% GP"
        case totalRx = "Total Rx"
        case grossProfit = "Gross Profit"
        case totalReceived = "Total Received"
        case date = "Date"
        case copay = "Copay"
        case acquisitionCost = "Acquisition Cost"
        case averageGP = "Average GP"
        case tpRemitted = "TP Remitted"
    }
}

解码注意事项

解码时需配置JSONDecoder的日期策略,适配createdTime的ISO 8601格式:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

// 假设data为API返回的Data对象
do {
    let record = try decoder.decode(Record.self, from: data)
    print(record)
} catch {
    print("解码失败:\(error)")
}

如果需要把fields.date也转为Date类型,可修改Fields中date的类型为Date,并给JSONDecoder添加多格式日期解析逻辑:

// 修改Fields中的date类型
let date: Date

// 配置支持两种日期格式的解码器
decoder.dateDecodingStrategy = .custom { decoder in
    let container = try decoder.singleValueContainer()
    let dateString = try container.decode(String.self)
    
    // 先解析createdTime的ISO8601格式
    if let date = ISO8601DateFormatter().date(from: dateString) {
        return date
    }
    // 再解析fields.date的yyyy-MM-dd格式
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    guard let date = formatter.date(from: dateString) else {
        throw DecodingError.dataCorruptedError(in: container, debugDescription: "无法解析日期字符串:\(dateString)")
    }
    return date
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:36:22