Swift - чтение файла JSON
Я новичок в Swift - пытаюсь прочитать файл JSON из URL. Моя попытка ниже.
JSON выглядит корректно - я протестировал его с JSONLint, но он продолжает падать.
Мысли?
func getRemoteJsonFile() -> NSDictionary {
//Create a new url
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
//check if its nil
if let actualRemoteUrl = remoteUrl {
//try to get the data
let filedata:NSData? = NSData(contentsOfURL: actualRemoteUrl)
//check if its nil
if let actualFileData = filedata {
//parse out the dictionaries
let jsonDict = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.AllowFragments, error: nil) as NSDictionary
return jsonDict
}
}
return NSDictionary()
}
2 ответа
Обновите свой код с этим:
func getRemoteJsonFile() -> [NSDictionary] {
// Create a new URL
let remoteUrl:NSURL? = NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")
let urlString:String = "\(remoteUrl)"
// Check if it's nil
if let actualRemoteUrl = remoteUrl {
// Try to get the data
let fileData:NSData? = NSData(contentsOfURL: actualRemoteUrl)
// Check if it's nil
if let actualFileData = fileData {
// Parse out the dictionaries
let arrayOfDictionaries:[NSDictionary]? = NSJSONSerialization.JSONObjectWithData(actualFileData, options: NSJSONReadingOptions.MutableContainers, error: nil) as [NSDictionary]?
if let actualArrayOfDictionaries = arrayOfDictionaries {
// Successfully parsed out array of dictionaries
return actualArrayOfDictionaries
}
}
}
return [NSDictionary]()
}
Это работает нормально для меня.
Мне потребовалась секунда, чтобы понять, поэтому я не виню вас за то, что вы пропустили это.
JSON, с которым вы связаны, минимизирован, поэтому трудно увидеть структуру. Давайте посмотрим (фрагмент) на него после прохождения через преттификатор:
[
{
"PlayerId":2501863,
"PlayerName":"Peyton Manning",
"PlayerTeam":"DEN",
"PlayerPosition":"QB",
"PlayerPassingYards":4727,
"PlayerPassingTDs":39,
"PlayerInterceptions":15,
"PlayerRushingYards":-24,
"PlayerRushingTDs":0,
"PlayerReceivingYards":0,
"PlayerReceivingTDs":0,
"PlayerReturnYards":0,
"PlayerReturnTDs":0,
"PlayerFumbleTDs":0,
"PlayerTwoPointConversions":2,
"PlayerFumblesLost":2,
"PlayerTeamLogo":"http://i.nflcdn.com/static/site/7.0/img/logos/teams-gloss-81x54/den.png"
}
]
Да. Он заключен в скобки, что означает, что это массив.
Это массив, поэтому вы не можете разыграть его какNSDictionary
, Вместо этого вы можете использовать его как NSArray
, но почему бы не использовать нативные типы Swift?
Что ж, если вам не нравятся типы, вы собираетесь это выяснить, но я все же думаю, что это лучший способ, потому что он заставляет вас думать о данных, которые вы анализируете.
Итак, у нас есть первая часть нашего определения типа для этой функции; это массив ([]
). Из каких компонентов состоит наш массив? Мы могли бы пойти с простым NSDictionary
, но мы делаем полные нативные типы здесь, поэтому давайте использовать нативный словарь Swift.
Чтобы сделать это, мы должны знать типы словаря (синтаксис для собственного типа словаря [KeyType: ValueType]
). Изучение JSON показывает, что все ключи String
s, но значения бывают разных типов, поэтому мы можем использовать AnyObject
,
Это дает нам тип словаря [String: AnyObject]
и весь наш JSON является массивом этого, поэтому последний тип [[String: AnyObject]]
(Вот это да).
Теперь, когда у нас есть правильный тип, мы можем изменить функцию, которую вы используете, чтобы немного проанализировать JSON.
Прежде всего, давайте использовать наш новый тип для возвращаемых и приведенных значений. Затем давайте сделаем тип возвращаемого значения необязательным на случай, если что-то пойдет не так, и добавим error
переменная для документирования этого.
Очищенная функция будет выглядеть примерно так:
func getData() -> [[String: AnyObject]]? {
let data: NSData? = NSData(contentsOfURL: NSURL(string: "http://nfl-api.azurewebsites.net/myplayers.json")!)
if let req: NSData = data {
var error: NSError?
if let JSON: [[String: AnyObject]] = NSJSONSerialization.JSONObjectWithData(req, options: NSJSONReadingOptions.AllowFragments, error: &error) as? [[String: AnyObject]] {
return JSON
}
}
return nil
}
Это оно!
Теперь мы можем вызвать функцию и извлечь значения из нашего [[String: AnyObject]]
(опять вау) вот так:
if let data: [[String: AnyObject]] = getData() {
println(data[0]["PlayerName"]!) // Peyton Manning
}