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

SwiftUI中如何异步解析非数组格式的API JSON响应?

解决SwiftUI中非数组JSON解析的问题

直接错误的修复

  1. 初始化Response实例的错误
    你的Response结构体没有默认初始化器(因为它的属性BillingAccount和TechnicalSupport都是自定义结构体,且没有默认值),所以不能直接用Response()创建实例。将results改为可选类型,初始值设为nil:

    @State private var results: Response?
    
  2. 错误的赋值语句
    解码后的decodedResponse本身就是Response类型的实例,它不存在Response这个成员属性。直接将解码结果赋值给results即可:

    results = decodedResponse
    

其他关键问题的修复(否则解析仍会失败)

除了上述两个直接错误,还有几个会导致解析失败或运行错误的问题:

  • 数值类型不匹配:JSON中的AccountBalance和TransactionCost是浮点数(如999.99),但你定义为Int,会导致解码失败。改为Double类型,同时新增ExtraInformation字段匹配JSON结构:

    struct BillingAccount: Codable {
        var AccountType: String
        var AccountBalance: Double
        var TransactionCost: Double
        var ExtraInformation: [String: Any]?
    }
    
  • 属性名与JSON字段不匹配:
    JSON中的QueryDurationMs、SupportInformationList与你结构体中的属性名不一致,直接修改属性名与JSON保持一致:

    struct TechnicalSupport: Codable {
        var ServerId: String
        var RequestId: String
        var QueryDurationMs: Int
        var SupportDate: String
        var SupportTime: String
        var SupportCode: String
        var SupportInformationList: [String]
    }
    
  • 视图中属性访问路径错误:原来的Text(results.AccountType)无法正确访问属性,需通过BillingAccount层级访问,同时处理可选值:

    Text(results?.BillingAccount.AccountType ?? "Loading...")
    
  • URL变量名错误:URL字符串中使用的domainName和apiKey与你定义的变量名domain、apikey不一致,修正后:

    guard let url = URL(string: "\(domain)/api/datapackage/\(type)?v=2&api_nullitems=1&auth_apikey=\(apikey)&key_content=\(content)") else {
        print("Invalid URL")
        return
    }
    
  • 错误处理优化:使用try替代try?,这样能捕获并打印具体的解码错误,便于调试:

    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
        results = decodedResponse
    } catch {
        print("解析错误: \(error)")
    }
    

完整修正后的代码

struct Response: Codable {
    var BillingAccount: BillingAccount
    var TechnicalSupport: TechnicalSupport
}

struct BillingAccount: Codable {
    var AccountType: String
    var AccountBalance: Double
    var TransactionCost: Double
    var ExtraInformation: [String: Any]?
}

struct TechnicalSupport: Codable {
    var ServerId: String
    var RequestId: String
    var QueryDurationMs: Int
    var SupportDate: String
    var SupportTime: String
    var SupportCode: String
    var SupportInformationList: [String]
}

struct ContentView: View {
    @State private var results: Response?
    
    let domain = "https://www.domainName.co"
    @State var type: String = "type"
    @State var apikey: String = "apiKey"
    @State var content: String = "content"
    
    var body: some View {
        Text(results?.BillingAccount.AccountType ?? "Loading...")
            .task {
                await loadData()
            }
    }
    
    func loadData() async {
        guard let url = URL(string: "\(domain)/api/datapackage/\(type)?v=2&api_nullitems=1&auth_apikey=\(apikey)&key_content=\(content)") else {
            print("Invalid URL")
            return
        }
        
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
            results = decodedResponse
        } catch {
            print("解析错误: \(error)")
        }
    }
}

问题原因总结

  1. 自定义结构体没有默认初始化器,无法直接创建空实例;
  2. 错误地尝试访问解码结果中不存在的Response成员;
  3. 结构体属性类型、名称与JSON字段不匹配,导致解码失败;
  4. 视图中属性访问路径错误,且未处理可选值;
  5. URL构建时变量名拼写错误,导致无效URL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:24:55