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

Swift中初始化JSON解析结构体时,如何正确声明Array类型?

关于Swift结构体解析JSON中times数组的问题

嘿,你的times数组的类型声明其实是完全正确的!JSON里的times字段就是一个字符串数组,所以[String]完全匹配这个结构。不过有两个关键细节需要注意,不然可能会导致解析失败:

1. JSON格式的合法性问题

你提供的JSON代码里,键名没有用双引号包裹(比如stop_id: "M1"),这不符合JSON的规范。合法的JSON应该是这样的:

{
  "stop_id": "M1",
  "transloc_stop_id": "4160714",
  "stop_name": "blank",
  "stop_desc": "blank",
  "stop_lat": "142",
  "stop_lon": "-171",
  "direction_id": "1",
  "times": [
    "7:00 AM",
    "7:30 AM",
    "8:00 AM",
    "8:30 AM",
    "8:45 AM",
    "9:00 AM",
    "9:30 AM",
    "10:00 AM",
    "10:30 AM",
    "11:00 AM",
    "11:30 AM"
  ]
}

一定要确保你的JSON文件是符合规范的,否则解析器会直接抛出错误。

2. 结构体属性与JSON键名的映射问题

你的结构体用的是驼峰命名(比如stopId),但JSON里的键是下划线分隔(比如stop_id),默认情况下Decodable无法自动匹配这两种命名风格,所以需要做一点配置:

方法一:手动定义CodingKeys枚举

在结构体里添加一个枚举,明确每个属性对应的JSON键名:

struct StopDescription: Decodable {
    let stopId: String
    let translocStopId: String
    let stopName: String
    let stopDesc: String
    let stopLat: String
    let stopLon: String
    let directionId: String
    let times: [String]
    
    // 手动映射键名
    enum CodingKeys: String, CodingKey {
        case stopId = "stop_id"
        case translocStopId = "transloc_stop_id"
        case stopName = "stop_name"
        case stopDesc = "stop_desc"
        case stopLat = "stop_lat"
        case stopLon = "stop_lon"
        case directionId = "direction_id"
        case times // 这个属性名和JSON键名一致,不需要额外映射
    }
}

方法二:使用自动蛇形转换策略

如果你不想手动写CodingKeys,可以给JSONDecoder设置键解码策略,让它自动把下划线命名转换成驼峰:

// 初始化解码器并设置策略
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

// 假设jsonData是你的JSON文件转换来的数据
do {
    let stop = try decoder.decode(StopDescription.self, from: jsonData)
    print("解析成功!第一个时间点:\(stop.times.first ?? "")")
} catch {
    print("解析失败:\(error.localizedDescription)")
}

额外优化建议

如果之后你需要把这些时间字符串转换成Date类型来做时间相关的操作,可以把times的类型改成[Date],然后配置JSONDecoder的日期解码策略:

// 先配置日期格式器
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "h:mm a"
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // 确保解析AM/PM时不受系统区域影响

// 设置解码器的日期策略
decoder.dateDecodingStrategy = .formatted(dateFormatter)

// 此时结构体的times可以改成[Date]
struct StopDescription: Decodable {
    // ... 其他属性不变
    let times: [Date]
}

这样就能直接拿到日期对象,方便后续的时间计算或展示啦。

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

相关产品推荐
方舟 Agent Plan

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

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