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

Swift4 Codable解码空数组问题求助

解决Swift Codable解码空数组失败的问题

你遇到的问题其实不是空数组导致的解码失败,而是JSON中部分字段的类型和Swift结构体定义不匹配,引发了解码错误,让你误以为是空数组的锅。下面具体分析并给出解决方案:

问题根源

看你的JSON数据,customer_id是数字类型(比如825),但你在Details结构体里把它定义成了String?类型。直接用try values.decode(String.self, forKey: .customer_id)解码时,类型不匹配会抛出错误,导致整个Details初始化失败,最终details变成nil,你才会误以为是address空数组的问题。

而空数组[]其实是Codable原生支持的,不需要特殊处理——它会被正常解码为空的[Address]数组(如果是可选类型就是Some([]))。

解决方案

方案一:修正字段类型匹配(推荐)

直接把结构体中类型不匹配的字段改成和JSON一致的类型,比如把customer_id改成Int?,这样可以完全依赖Codable的默认实现,不需要自定义解码方法:

import Foundation

struct Signup: Codable {
    var success: String?
    var message: String?
    var details: Details?
    // 无需自定义CodingKeys和init(from:),默认就能处理所有字段
}

struct Details: Codable {
    var address: [Address]?
    var cart_count: String?
    var customer_id: Int? // 改为Int类型,匹配JSON的数字类型
    var customer_status: String?
    var email: String?
    var firstname: String?
    var full_name: String?
    var is_customer_verified: String?
    var is_delivery_available: String?
    var is_registration_complete: String?
    var lastname: String?
    var mobile: String?
    var name_type: String?
    var pincode: String?
    var profile_pic: String?
    var referral_code: String?
    // 无需自定义CodingKeys和init(from:)
}

struct Address: Codable {
    var address_default: String?
    var address_id: String?
    var address_type: String?
    var city: String?
    var customer_id: String?
    var flat_or_house_or_office_no: String?
    var full_address: String?
    var full_name: String?
    var landmark: String?
    var lat: String?
    var lng: String?
    var mobile: String?
    var name_type: String?
    var pincode: String?
    var street_or_society_or_office_name: String?
}

方案二:保留String类型,自定义处理类型转换

如果业务要求customer_id必须是String?类型,那需要在自定义解码方法中处理Int转String的逻辑,同时空数组直接正常解码即可:

struct Details: Codable {
    var address: [Address]?
    var cart_count: String?
    var customer_id: String?
    var customer_status: String?
    var email: String?
    var firstname: String?
    var full_name: String?
    var is_customer_verified: String?
    var is_delivery_available: String?
    var is_registration_complete: String?
    var lastname: String?
    var mobile: String?
    var name_type: String?
    var pincode: String?
    var profile_pic: String?
    var referral_code: String?
    
    private enum CodingKeys: String, CodingKey {
        case address, cart_count, customer_id, customer_status, email, firstname, full_name, is_customer_verified, is_delivery_available, is_registration_complete, lastname, mobile, name_type, pincode, profile_pic, referral_code
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        
        // 空数组直接正常解码,无需try?
        address = try values.decode([Address].self, forKey: .address)
        
        cart_count = try values.decode(String.self, forKey: .cart_count)
        
        // 处理customer_id的类型转换:先尝试解码Int,再转成String;如果本身是String就直接解码
        if let customerIdInt = try? values.decode(Int.self, forKey: .customer_id) {
            customer_id = String(customerIdInt)
        } else {
            customer_id = try values.decode(String.self, forKey: .customer_id)
        }
        
        // 其他字段正常解码
        customer_status = try values.decode(String.self, forKey: .customer_status)
        email = try values.decode(String.self, forKey: .email)
        firstname = try values.decode(String.self, forKey: .firstname)
        full_name = try values.decode(String.self, forKey: .full_name)
        is_customer_verified = try values.decode(String.self, forKey: .is_customer_verified)
        is_delivery_available = try values.decode(String.self, forKey: .is_delivery_available)
        is_registration_complete = try values.decode(String.self, forKey: .is_registration_complete)
        lastname = try values.decode(String.self, forKey: .lastname)
        mobile = try values.decode(String.self, forKey: .mobile)
        name_type = try values.decode(String.self, forKey: .name_type)
        pincode = try values.decode(String.self, forKey: .pincode)
        profile_pic = try values.decode(String.self, forKey: .profile_pic)
        referral_code = try values.decode(String.self, forKey: .referral_code)
    }
}

总结

  • Codable原生支持空数组解码,不需要额外处理;
  • 解码失败的核心原因是JSON字段类型与Swift结构体字段不匹配,优先修正类型或自定义处理类型转换;
  • 尽量避免不必要的自定义解码方法,减少出错概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:08:11