2016-05-23 90 views
0

我想解析來自端點的所有數據並將其分配給常量,以便我可以在ViewController類中使用它們。我最大的問題是將「key」數組的每個項目分配給常量。誰能幫我嗎?解析json到swift常量

static func fetchRates(completionHandler: (current: [Currency]) ->()) { 

    let urlString = "https://api.bitcoinaverage.com/ticker/all" 
    let url = NSURL(string: urlString) 
    NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (location, response, error) -> Void in 

     do { 
      let json = try(NSJSONSerialization.JSONObjectWithData(location!, options: .MutableContainers)) 
      let tickerData = [Currency]() 

      for key in json as! [String : AnyObject] { 

      } 

      dispatch_async(dispatch_get_main_queue(), {() -> Void in 
       completionHandler(current: tickerData) 
      }) 

     } catch let err as NSError { 
      print(err) 
     } 

    }).resume() 
    } 

這是來自端點的響應。

{ 
"AUD": { 
"24h_avg": 621.17, 
"ask": 624.12, 
"bid": 620.3, 
"last": 620.45, 
"timestamp": "Mon, 23 May 2016 20:01:16 -0000", 
"total_vol": 671.28 
}, 
"BRL": { 
"24h_avg": 1725.77, 
"ask": 1748.83, 
"bid": 1731.8, 
"last": 1738.64, 
"timestamp": "Mon, 23 May 2016 20:01:16 -0000", 
"total_vol": 534.19 
}, 
"CAD": { 
"24h_avg": 579.2, 
"ask": 579.27, 
"bid": 573.57, 
"last": 577.42, 
"timestamp": "Mon, 23 May 2016 20:01:16 -0000", 
"total_vol": 413.81 
}, 
+0

你可以打印您的JSON和共享的結果,這樣我可以舉一個具體的例子嗎? –

+0

我添加了對我的問題的回覆。 @AkshanshThakur – Court

+0

關鍵的「數組」是字典,如何賦值取決於「貨幣」類的結構 – vadian

回答

0

試試這個:

for (key, value) in (json as! [String: AnyObject]) { 
    let currencyData = value as! [String: AnyObject] 
    // key is the currency code: AUD, BRL, etc 
    // currencyData is the details: ask, bid, last, ... 
} 
0

這裏有一個粗略的和現成的解決方案,但它是你可以建立一個開始。通過定義一些方便的類型

讓我們開始:

// Define a handy result type 
// See https://github.com/antitypical/Result if you want a more detailed implementation. 
public enum Result<T> { 
    case Success(T) 
    case Error(ErrorType) 
} 

// Define an error type for inconsistentData 
public enum DataError: ErrorType { 
    case NoData 
} 

// Define a struct to hold a Currency 
public struct Currency: CustomStringConvertible, Equatable { 
    let currencyCode: String 
    let dayAverage: Double 
    let ask: Double 
    let bid: Double 
    let last: Double 
    let timestamp: String 
    let totalVolume: Double 

    // This makes it easier to debug 
    public var description: String { 
     return "currencyCode: \(currencyCode), dayAverage: \(dayAverage), ask: \(ask), bid: \(bid), last: \(last), timestamp: \(timestamp), totalVolume: \(totalVolume)" 
    } 

    public init(currencyCode: String, 
       dayAverage: Double, 
       ask: Double, 
       bid: Double, 
       last: Double, 
       timestamp: String, 
       totalVolume: Double) { 
     self.currencyCode = currencyCode 
     self.dayAverage = dayAverage 
     self.ask = ask 
     self.bid = bid 
     self.last = last 
     self.timestamp = timestamp 
     self.totalVolume = totalVolume 
    } 
} 

// Make sure your structs conform to Equatable. 
public func == (lhs: Currency, rhs: Currency) -> Bool { 
    return 
     lhs.currencyCode == rhs.currencyCode && 
      lhs.dayAverage == rhs.dayAverage && 
      lhs.ask == rhs.ask && 
      lhs.bid == rhs.bid && 
      lhs.last == rhs.last && 
      lhs.timestamp == rhs.timestamp && 
      lhs.totalVolume == rhs.totalVolume 
} 

// I like to define convenience initialisers outside of the struct. Keeps things less coupled. 
public extension Currency { 

    public init?(currencyCode: String, values: [String : AnyObject]) { 
     guard 
      let dayAverage = values["24h_avg"] as? Double, 
      let ask = values["ask"] as? Double, 
      let bid = values["bid"] as? Double, 
      let last = values["last"] as? Double, 
      let timestamp = values["timestamp"] as? String, 
      let totalVolume = values["total_vol"] as? Double 
      else { return nil } 

     self = Currency(currencyCode: currencyCode, 
         dayAverage: dayAverage, 
         ask: ask, 
         bid: bid, 
         last: last, 
         timestamp: timestamp, 
         totalVolume: totalVolume) 
    } 
} 

我們取值的功能可以寫爲:

// The function to fetch the currencies. 
// Use a richer type for the completion parameter. It is either a success with a list of currencies or an error. 
public func fetchRates(completionHandler: (Result<[Currency]>) ->()) { 
    let url = NSURL(string: "https://api.bitcoinaverage.com/ticker/all")! // Force unwrapped as we assume this is a valid URL 

    NSURLSession.sharedSession().dataTaskWithURL(url) { (data, _, error) in 
     if let error = error { 
      completionHandler(.Error(error)) 
      return 
     } 

     do { 
      guard 
       let data = data, 
       // Being generous with the type of the result because there is a top level key that is the timestamp not related to a currency. 
       let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? [String : AnyObject] 
       else { 
        completionHandler(.Error(DataError.NoData)) 
        return 
      } 

      var currencies = [Currency]() 

      for (key, value) in json { 
       guard 
        // Make sure that the values we are about to pass on are of the correct type. 
        let value = value as? [String : AnyObject], 
        let currency = Currency(currencyCode: key, values: value) 
        else { continue } 
       currencies.append(currency) 
      } 

      print(currencies) 

      completionHandler(.Success(currencies)) 

     } catch { 
      completionHandler(.Error(error)) 
     } 

     }.resume() 
} 

而且你可以運行與完成處理,因爲這功能:

fetchRates { result in 
    dispatch_async(dispatch_get_main_queue()) { 
     switch result { 
     case .Success(let currencies): 
      for currency in currencies { 
       print(currency) 
      } 
     case .Error(let error): 
      print(error) 
     }   
    } 
} 

你可以下載遊樂場,你可以看到所有這些工作在:

https://dl.dropboxusercontent.com/u/585261/Currency.playground.zip