Swift中如何解析单个JSON数据块而非完整JSON序列?附现有代码
解决方案:只解析并存储第一个时间序列数据块
没问题!AlphaVantage返回的Time Series FX (5min)是一个以时间戳为键的字典,而且默认是按从新到旧的顺序排列的,所以要拿到第一个(最新的)数据块,我们可以在现有解码逻辑的基础上稍作修改,这里给你三种实用的方案:
方案1:解析完整数据后提取第一条(最简单)
保持你原有的解码代码不变,在解析完成后直接提取字典的第一个元素即可。从iOS 13/macOS 10.15开始,Swift的Dictionary会保留JSON返回的键顺序,所以first方法就能拿到最新的那条数据:
let jsonUrlString = "https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=EUR&to_symbol=USD&interval=5min&apikey=demo" let urlObj = URL(string: jsonUrlString) URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in guard let data = data else { return } do { let forex = try JSONDecoder().decode(Root.self, from: data) // 安全提取第一个时间序列条目 if let firstEntry = forex.timeSeriesFX5Min.first { let latestTimestamp = firstEntry.key // 最新的时间戳,比如"2024-05-20 15:05:00" let latestForexData = firstEntry.value // 对应的汇率数据(Forex结构体实例) // 这里可以直接操作这条数据,或者存储到变量/结构体中 print("最新时间: \(latestTimestamp)") print("开盘价: \(latestForexData.the1Open)") print("最高价: \(latestForexData.the2High)") } } catch { print(error) } }.resume() } // 原有的结构体保持不变 struct Root: Codable { let timeSeriesFX5Min: [String:Forex] enum CodingKeys: String, CodingKey { case timeSeriesFX5Min = "Time Series FX (5min)" } } struct Forex: Codable { let the1Open, the2High, the3Low, the4Close: String enum CodingKeys: String, CodingKey { case the1Open = "1. open" case the2High = "2. high" case the3Low = "3. low" case the4Close = "4. close" } }
方案2:兼容旧系统的写法(iOS 12及以下)
如果需要兼容更早的系统,由于旧版本Swift的字典不保证顺序,我们可以先对时间戳键进行排序,取最大的那个(因为时间戳字符串的字典序和时间顺序一致,最新的时间戳字符串最大):
do { let forex = try JSONDecoder().decode(Root.self, from: data) // 按时间戳降序排序,取第一个就是最新的 let sortedTimestamps = forex.timeSeriesFX5Min.keys.sorted(by: >) if let latestTimestamp = sortedTimestamps.first, let latestForexData = forex.timeSeriesFX5Min[latestTimestamp] { // 操作最新数据 print("最新时间: \(latestTimestamp)") print("收盘价: \(latestForexData.the4Close)") } } catch { print(error) }
方案3:封装成单独的结构体(更优雅)
如果你想专门存储这条最新数据,可以创建一个新的结构体,把时间戳和汇率数据整合在一起,方便后续统一操作:
// 新增一个结构体用于存储单条最新数据 struct LatestForexEntry: Codable { let timestamp: String let open: String let high: String let low: String let close: String } // 解码后转换为这个结构体 do { let forex = try JSONDecoder().decode(Root.self, from: data) if let firstEntry = forex.timeSeriesFX5Min.first { let latestEntry = LatestForexEntry( timestamp: firstEntry.key, open: firstEntry.value.the1Open, high: firstEntry.value.the2High, low: firstEntry.value.the3Low, close: firstEntry.value.the4Close ) // 现在可以直接操作latestEntry,比如存入数组、展示到UI等 print(latestEntry) } } catch { print(error) }
关键说明
- AlphaVantage的时间序列数据默认是降序排列的,所以第一个元素就是最新的汇率数据。
- 所有方案都用了
if let安全解包,避免字典为空时出现崩溃。
内容的提问来源于stack exchange,提问作者Leone Mitchell
相关产品推荐
相关产品推荐

