解析 JSON Swift 3 CTA 火车跟踪器

Posted

技术标签:

【中文标题】解析 JSON Swift 3 CTA 火车跟踪器【英文标题】:Parsing JSON Swift 3 CTA Train Tracker 【发布时间】:2017-05-16 04:26:09 【问题描述】:

我正在尝试解析 CTA 火车到达的 JSON。


ctatt =     
    errCd = 0;
    errNm = "<null>";
    eta =         (
                    
            arrT = "2017-05-15T23:22:32";
            destNm = Howard;
            destSt = 30173;
            flags = "<null>";
            heading = 305;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.91065";
            lon = "-87.64918";
            prdt = "2017-05-15T23:18:32";
            rn = 843;
            rt = Red;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Howard";
            stpId = 30255;
            trDr = 1;
        ,
                    
            arrT = "2017-05-15T23:21:45";
            destNm = "95th/Dan Ryan";
            destSt = 30089;
            flags = "<null>";
            heading = 91;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.95377";
            lon = "-87.65493";
            prdt = "2017-05-15T23:17:45";
            rn = 836;
            rt = Red;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward 95th/Dan Ryan";
            stpId = 30256;
            trDr = 5;
        ,
                    
            arrT = "2017-05-15T23:27:28";
            destNm = Kimball;
            destSt = 30249;
            flags = "<null>";
            heading = 357;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.90563";
            lon = "-87.63712";
            prdt = "2017-05-15T23:18:28";
            rn = 426;
            rt = Brn;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Kimball or Linden";
            stpId = 30257;
            trDr = 1;
        ,
                    
            arrT = "2017-05-15T23:27:16";
            destNm = Loop;
            destSt = 30249;
            flags = "<null>";
            heading = 89;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.96641";
            lon = "-87.67864";
            prdt = "2017-05-15T23:18:16";
            rn = 427;
            rt = Brn;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Loop";
            stpId = 30258;
            trDr = 5;
        ,
                    
            arrT = "2017-05-15T23:28:25";
            destNm = "95th/Dan Ryan";
            destSt = 30089;
            flags = "<null>";
            heading = 178;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.97345";
            lon = "-87.65853";
            prdt = "2017-05-15T23:18:25";
            rn = 939;
            rt = Red;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward 95th/Dan Ryan";
            stpId = 30256;
            trDr = 5;
        ,
                    
            arrT = "2017-05-15T23:32:01";
            destNm = Howard;
            destSt = 30173;
            flags = "<null>";
            heading = 357;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "41.87815";
            lon = "-87.6276";
            prdt = "2017-05-15T23:18:01";
            rn = 928;
            rt = Red;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Howard";
            stpId = 30255;
            trDr = 1;
        ,
                    
            arrT = "2017-05-15T23:37:32";
            destNm = "95th/Dan Ryan";
            destSt = 30089;
            flags = "<null>";
            heading = 162;
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 0;
            lat = "42.00566";
            lon = "-87.66565";
            prdt = "2017-05-15T23:18:32";
            rn = 926;
            rt = Red;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward 95th/Dan Ryan";
            stpId = 30256;
            trDr = 5;
        ,
                    
            arrT = "2017-05-15T23:40:41";
            destNm = Kimball;
            destSt = 0;
            flags = "<null>";
            heading = "<null>";
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 1;
            lat = "<null>";
            lon = "<null>";
            prdt = "2017-05-15T23:18:41";
            rn = 431;
            rt = Brn;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Kimball or Linden";
            stpId = 30257;
            trDr = 1;
        ,
                    
            arrT = "2017-05-15T23:40:41";
            destNm = "See train";
            destSt = 0;
            flags = "<null>";
            heading = "<null>";
            isApp = 0;
            isDly = 0;
            isFlt = 0;
            isSch = 1;
            lat = "<null>";
            lon = "<null>";
            prdt = "2017-05-15T23:18:41";
            rn = 434;
            rt = Brn;
            staId = 41320;
            staNm = Belmont;
            stpDe = "Service toward Loop";
            stpId = 30258;
            trDr = 5;
        
    );
    tmst = "2017-05-15T23:18:54";
;

在我的ViewController.swift

import UIKit

class ViewController: UIViewController 

override func viewDidLoad() 
    super.viewDidLoad()

    let url = URL(string: "http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=individualkeygoeshere&mapid=41320&outputType=JSON")

    let task = URLSession.shared.dataTask(with: url!)  (data, response, error) in
        if error != nil
        
            print("Error")
        
        else 
            if let content = data
            
                do 
                    let myJSON = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject

                    if let ctattimetable = myJSON["ctatt"] as? [String:Any] 
                        if let estArrivalTime = ctattimetable["eta"] as? [Any] 
                            print(estArrivalTime)
                            if let stationName = estArrivalTime["staNm"] 
                                print(stationName)
                            
                        
                    
                
                catch 
                
            
        
    
    task.resume()


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


我还没有一个特定的目标,只是想在Swift 3 中解析JSON。因此,在这种情况下,我要做的是获取每个 eta 的站名(JSON 中的 staNm),所以基本上我希望得到 Belmont 作为响应。我收到 swift 编译器错误,无法使用“String”类型的索引来下标“[Any]”类型的值。我被困在如何从 eta 获取每个键的值。有人知道我会怎么做吗? CTA 火车跟踪器 API 的文档在这里:http://www.transitchicago.com/developers/ttdocs/default.aspx

【问题讨论】:

谢谢大家!所有这些答案都有帮助,希望我能全部选择 【参考方案1】:

etaDictionary 的数组,数组不能是subscriptString 类型,你可以用Int 为数组下标,如果你想从中访问特定的键,你需要简单地遍历数组您还需要将其指定为字典数组,而不是将 eta 指定为 Any 的数组。

do 
    let myJSON = try JSONSerialization.jsonObject(with: content, options: []) as? [String:Any] ?? [:]

    if let ctattimetable = myJSON["ctatt"] as? [String:Any] 
        if let estArrivalTime = ctattimetable["eta"] as? [[String:Any]] 
             for item in estArrivalTime 
                 if let stationName = item["staNm"] as? String 
                     print(stationName)
                 
                 //You can access other keys here on item dictionary same way like staNm
             
         
     

catch 

【讨论】:

【参考方案2】:
if let ctattimetable = myJSON["ctatt"] as? [String : Any] 
            if let estArrivalTime = ctattimetable["eta"] as? [[String : Any]] 
                for eta in estArrivalTime 
                    if let stationName = eta["staNm"] 
                        print(stationName)
                    
                
            
        

【讨论】:

【参考方案3】:

你在这句话中做错了

if let stationName = estArrivalTime["staNm"]

因为你从这个 if let 语句中得到了一个对象数组

if let estArrivalTime = ctattimetable["eta"] as? [Any]

因此,您必须使用此循环迭代此数组中的每个项目以获取 staNm

for item in estArrivalTime 
                 if let _staNm = item["staNm"] as? String 
                     print("staNm : \(_staNm)")
                 

             

【讨论】:

【参考方案4】:

JSON 是字典而不是 任何东西

let myJSON = try JSONSerialization.jsonObject(with: content) as! [String:Any]

eta 的值是一个字典数组,而不是 Anything

数组
if let estArrivalTime = ctattimetable["eta"] as? [[String:Any]]

如果您想要的不仅仅是打印键 staNm 的值,您需要将其转换为 String

更具体的类型,编译器不会抱怨。

一如既往,不要在 Swift 中使用 .mutableContainers。完全没有效果。

请阅读 Swift 博客中全面的 Apple 文章:Working with JSON in Swift

【讨论】:

以上是关于解析 JSON Swift 3 CTA 火车跟踪器的主要内容,如果未能解决你的问题,请参考以下文章

涉及 JSON 解析以及静态和动态 UITableView 单元格的 Swift3 项目 - 使其更加面向对象

使用 javascript 事件跟踪创建短代码以插入 CTA 按钮

text 使用Google Analytics(分析)启动按钮CTA事件跟踪

Swift 3 解析 JSON 嵌套问题

在 Swift 3 中解析 JSON 数组

使用未解析的标识符 'json' (Swift 3) (Alamofire)