Почему я не могу создать массив <[String: Any]>?Работа с Alamofire (Swift) - PullRequest
0 голосов
/ 24 мая 2019

Я создал модель, которая будет принимать все данные. К сожалению, мне было приказано работать с Alamofire. Но по какой-то причине массив arrayOfItem не создается. В чем может быть причина?

Это value из case .success(let value): здесь

func fetchData(from url: String) {

    guard let url = URL(string: url) else { return }

    request(url).validate().responseJSON { (dataResponse) in

        switch dataResponse.result {
        case .success(let value):
           // try to print --- value have data! 
            guard let arrayOfItem = value as? Array<[String : Any]> else { return }
           // try to print --- arrayOfItem is EMPTY!
            }
        case .failure(let error):
            print(error)
        }
    }
}

Отредактировано: добавить мою модель:

import Foundation

public struct Information: Decodable {

let copyright : String?
let numResults : Int?
let results : [Output]?
let status : String?

init(dict: [String: Any]) {

    let copyright = dict["copyright"] as? String
    let numResults = dict["numResults"] as? Int
    let results = dict["results"] as? [Output]
    let status = dict["status"] as? String

    self.copyright = copyright
    self.numResults = numResults
    self.results = results
    self.status = status
    }
}

import Foundation

public struct Output: Decodable {

let abstractField : String?
let adxKeywords : String?
let assetId : Int?
let byline : String?
let column : String?
let countType : String?
let desFacet : [String]?
let emailCount : Int?
let etaId : Int?
let geoFacet : [String]?
let id : Int?
let media : [Media]?
let nytdsection : String?
let orgFacet : String?
let perFacet : String?
let publishedDate : String?
let section : String?
let source : String?
let subsection : String?
let title : String?
let type : String?
let updated : String?
let uri : String?
let url : String?

init(dict: [String : Any]) {

    let abstractField = dict["abstractField"] as? String
    let adxKeywords = dict["adxKeywords"] as? String
    let assetId = dict["assetId"] as? Int
    let byline = dict["byline"] as? String
    let column = dict["column"] as? String
    let countType = dict["countType"] as? String
    let desFacet = dict["desFacet"] as? [String]
    let emailCount = dict["emailCount"] as? Int
    let etaId = dict["etaId"] as? Int
    let geoFacet = dict["geoFacet"] as? [String]
    let id = dict["id"] as? Int
    let media = dict[""] as? [Media]
    let nytdsection = dict["nytdsection"] as? String
    let orgFacet = dict["orgFacet"] as? String
    let perFacet = dict["perFacet"] as? String
    let publishedDate = dict["publishedDate"] as? String
    let section = dict["section"] as? String
    let source = dict["source"] as? String
    let subsection = dict["subsection"] as? String
    let title = dict["title"] as? String
    let type = dict["type"] as? String
    let updated = dict["updated"] as? String
    let uri = dict["uri"] as? String
    let url = dict["url"] as? String

    self.abstractField = abstractField
    self.adxKeywords = adxKeywords
    self.assetId = assetId
    self.byline = byline
    self.column = column
    self.countType = countType
    self.desFacet = desFacet
    self.emailCount = emailCount
    self.etaId = etaId
    self.geoFacet = geoFacet
    self.id = id
    self.media = media
    self.nytdsection = nytdsection
    self.orgFacet = orgFacet
    self.perFacet = perFacet
    self.publishedDate = publishedDate
    self.section = section
    self.source = source
    self.subsection = subsection
    self.title = title
    self.type = type
    self.updated = updated
    self.uri = uri
    self.url = url
    }
}
import Foundation

public struct Media: Decodable {

let approvedForSyndication : Bool?
let caption : String?
let copyright : String?
let mediaMetadata : [MediaMetadata]?
let subtype : String?
let type : String?

init(dict: [String: Any]) {
    let approvedForSyndication = dict["approvedForSyndication"] as? Bool
    let caption = dict["caption"] as? String
    let copyright = dict["copyright"] as? String
    let mediaMetadata = dict["mediaMetadata"] as? [MediaMetadata]
    let subtype = dict["subtype"] as? String
    let type = dict["type"] as? String

    self.approvedForSyndication = approvedForSyndication
    self.caption = caption
    self.copyright = copyright
    self.mediaMetadata = mediaMetadata
    self.subtype = subtype
    self.type = type

    }

}
import Foundation

public struct MediaMetadata: Decodable {

let format : String?
let height : Int?
let url : String?
let width : Int?

init(dict: [String: Any]) {
    let format = dict["format"] as? String
    let height = dict["height"] as? Int
    let url = dict["url"] as? String
    let width = dict["width"] as? Int

    self.format = format
    self.height = height
    self.url = url
    self.width = width
   }
}

Ответы [ 2 ]

1 голос
/ 24 мая 2019

в соответствии с JSON https://github.com/nytimes/public_api_specs/blob/master/most_popular_api/most_popular_api_v2.md

{   <<<< top root dictionary 
  "status":"OK",
  "copyright":"Copyright (c) 2010 The New York Times Company.  All Rights Reserved.",
  "num_results":94,
  "results":[{}]  <<<<< it's an array of dictionaries  
}

Ваш верхний корень - это словарь, а не массив

if let res = value as? [String: Any], let results = res["results"] as? [[String: Any]] {
    print(results)
 }

также лучше использовать Codable


Alamofire.request(URL(string:"urlStr")!, method: .get, parameters: [:], encoding: URLEncoding.default, headers: [:]).responseData { response in


    if response.result.isSuccess {

        guard let data = response.data else { return }

        do {

         let res = try JSONDecoder().decode(Information.self, from: data)
         print(res.results) 
        }
        catch {

            print(error)
        }
    } 
}
0 голосов
/ 24 мая 2019

Фактический JSON содержится в value, а не в. Так что используйте:

guard let value = value as? [String : Any] else { return }
let arrayOfItem = value["result"] as? [[String : Any]]
print(arrayOfItem)

Я смогу отладить больше, если вы добавите JSON, который вы получаете value.

Как вы сказали, value имеет тип Data, вы можете просто получить все данные, используя созданный вами тип Information, т.е.

if let data = dataResponse.data {
    let information = try? JSONDecoder().decode(Information.self, from: value)
    print(information)
}
...