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

升级至Swift4后Decodable结构体解码失败,求解决方案

解决Swift 4+中Codable解析JSON的结构体生成问题

嘿,我太懂你从Swift 3切换到Swift 4+时,突然要上手Encodable/Decodable(也就是合起来的Codable协议)的那种纠结了——刚接触的时候确实容易在结构体定义上卡壳。不过别慌,我们对着你给出的JSON一步步来,轻松搞定解码用的结构体。

首先先明确你要解析的JSON结构(我把你给出的内容补全了部分,方便演示):

{
"status": "true",
"message": "Valid request",
"data": {
"user_id": "16",
"first_name": "Hamidouh",
"last_name": "Semix",
"other_name": null,
"fullname": "Hamidouh Semix",
"alias": null,
"about": "",
"sex_id": "1",
"sex": "Male",
"birth_date": "1989-08-15"
}
}

第一步:拆分JSON层级

这个JSON是两层嵌套结构:

  • 顶层对象包含三个字段:status、message、data
  • data字段是一个嵌套的用户信息对象

第二步:定义对应的Swift结构体

我们需要分别定义顶层的响应结构体和嵌套的用户结构体,都遵循Codable协议(Swift会自动帮我们合成解码/编码所需的方法,不用手动写!)

方式一:直接匹配JSON的蛇形命名

如果不想额外处理字段命名,直接用JSON里的蛇形命名:

// 顶层响应结构体
struct APIResponse: Codable {
    let status: String
    let message: String
    let data: User
}

// 嵌套的用户信息结构体
struct User: Codable {
    let user_id: String
    let first_name: String
    let last_name: String
    let other_name: String?  // 因为JSON里是null,所以用可选类型
    let fullname: String
    let alias: String?       // 同理,null对应可选类型
    let about: String
    let sex_id: String
    let sex: String
    let birth_date: String   // 如果之后要转Date,可以改成Date类型,后面会说
}

方式二:用Swift风格的驼峰命名(更推荐)

如果你习惯Swift的驼峰命名(比如userId代替user_id),可以通过JSONDecoder的keyDecodingStrategy自动转换,不用手动写CodingKeys:

struct APIResponse: Codable {
    let status: String
    let message: String
    let data: User
}

struct User: Codable {
    let userId: String
    let firstName: String
    let lastName: String
    let otherName: String?
    let fullname: String
    let alias: String?
    let about: String
    let sexId: String
    let sex: String
    let birthDate: String
}

第三步:执行解码操作

不管用哪种命名方式,解码的逻辑都很简单,这里以驼峰命名的版本为例:

// 假设你已经获取到JSON数据(比如从网络请求得到的Data)
let jsonData: Data = ... 

do {
    let decoder = JSONDecoder()
    // 开启蛇形转驼峰的自动映射
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let response = try decoder.decode(APIResponse.self, from: jsonData)
    
    // 解码成功后就可以直接用数据了
    print("用户ID:\(response.data.userId)")
    print("用户全名:\(response.data.fullname)")
} catch {
    print("解码失败:\(error.localizedDescription)")
}

几个关键细节要注意

  • status是String不是Bool:你的JSON里status的值是字符串"true",不是布尔值true,所以结构体里必须定义为String类型,不然解码会直接失败!
  • 可选类型的使用:JSON里值为null的字段(比如other_name、alias),一定要定义为可选类型(String?),否则解码时遇到null会抛出错误。
  • 日期转换(可选):如果想把birth_date直接转成Swift的Date类型,可以修改User结构体的字段,并给解码器设置日期解析策略:
    // 修改User结构体的birthDate字段
    let birthDate: Date
    
    // 解码时添加日期策略
    decoder.dateDecodingStrategy = .iso8601
    
    注意:如果你的日期格式不是标准ISO8601,可能需要自定义日期解析器。

这样你就能顺利把JSON数据转换成Swift对象了,是不是比想象中简单?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:34:28