Использование Codable-Decodable и Guard

Я хочу проанализировать данные из вызова API и отобразить их в моем приложении. Я добился этого так...

Сначала структура сделана так...

struct GalleryDetails {
    let id: Int
    let customerID: String
    let title: String
    let description: String

    init(id : Int, customerID: String, title: String, description: String) {
        self.id = id
        self.customerID = customerID
        self.title = title
        self.description = description
    }
}

В ответ на мой вызов API я храню эти значения в моей структуре следующим образом...

func myAPICall() {
let url = "http://myApp.abc.de/myApp/public/……"

let headers = [….]

let Parameters = [….]

        Alamofire.request(url, method: .post, parameters: Parameters, encoding: URLEncoding.httpBody, headers: headers)

            .responseJSON { (response) in        
                if let httpResponse = response.response {

                    if httpResponse.statusCode == 200 {
                        if let result = response.result.value as? [String:Any] {

                             if let customerData = result["customer_data"] as? [[String: Any]] {

                                for result in customerData {
                                   if let id = result["id"] as? Int {
                                        self.myID = id
                                    }
                                    if let custId = result["customer_id"] as? String {
                                        self.theCustomerId = custId
                                    }

                                 if let title = result["title"] as? String {
                                        self.theTitle = title
                                    }
                                    if let description = result["description"] as? String {
                                        self.theDescription = description
                                    }

                               let galleryDetails = GalleryDetails(id: self.myID, customerID: self.theCustomerId, title: self.theTitle, description: self.theDescription)

                         self.galleryDataArray.append(galleryDetails)               

                        }
                    }
                }
            }
         }
       } 

Это работает нормально. Но мое беспокойство заключается в следующем...

  1. Я сделал простую структуру. Как я могу использовать Codable-Decodable структура вместо этой простой структуры..?

  2. При разборе, как я могу использовать guard утверждение вместо нескольких if-lets

3 ответа

struct GalleryDetails: Decodable {
      let id: Int
      let customerID: String
      let title: String
      let description: String

      init(id : Int, customerID: String, title: String, description: String) {
        self.id = id
        self.customerID = customerID
        self.title = title
        self.description = description
    }

    enum CodingKeys: String, CodingKey {
        case customerID = "customer_id"
        case id
        case title
        case description
    }
}

struct CustomerData: Decodable {
    let galleryDetails: [GalleryDetails]
    enum CodingKeys: String, CodingKey {
        case galleryDetails = "customer_data"
    }
}

let url = "http://myApp.abc.de/myApp/public/……”
let headers = [….]
let Parameters = [….]

Alamofire.request(url, method: .post, parameters: [:], encoding: .httpBody, headers: headers).responseJSON { (response) in
    guard let httpResponse = response.response, httpResponse.statusCode == 200 else { return }
    let data = response.data
    do {
        let customerData = try JSONDecoder().decode(CustomerData.self, from: data)
        let galleryDetails = customerData.galleryDetails
        self.galleryDataArray.append(galleryDetails)
    } catch {
        fatalError("JSON Parsing error")
    }
}

Codable и это подварианты (Encodable/Decodable) "просто работай", как говорит Apple. Вам просто нужно использовать JSONEncoder()/JSONDecoder() разобрать их.

Допустим, у вас есть этот JSON, возвращенный с сервера:

{
    "userid": 10,
    "name": "Alejandro"
}

и эта структура:

struct Person {
    let userId: Int
    let name: String
}

вы можете сделать его соответствующим Codable, используя это расширение:

extension Person: Codable {
    enum CodingKeys: String, CodingKey {
        case name
        case userId = "userid" // Matches "userId" to "userid" that comes from the JSON
    }
}

Тогда как мне декодировать тот JSON, который исходит от Alamofire?

let url: URLConvertible = URL(string: "http://myserviceurl.com/path.json")!

Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { response in
    guard let data = response.data else {
        print("ERROR!")
        return
    }

    // Let's decode here
    do {
        let myObject = try JSONDecoder().decode(Person.self, from: data)
        // Here "myObject" is of type "Person"
        print("My object is: \(myObject)")
    } catch {
        print("ERROR DECODING!")
    }
}

Вам не нужно реализовывать пользовательский инициализатор, если ваш ответ представляет Person, Если вы получаете, с другой стороны, множество людей, то вы можете реализовать свой собственный init (или, что еще проще, просто реализовать другой Codable структура, которая содержит людей внутри).

Если ваш ответ потенциально может вернуться nil значения, например middlename или же age, просто добавьте его как необязательный, и все должно быть в порядке:

struct Person {
    let userId: Int
    let name: String
    var age: Int?
    var middleName: String?
}

extension Person: Codable {
    enum CodingKeys: String, CodingKey {
        case name, age
        case userId = "userid" // Matches "userId" to "userid" that comes from the JSON
        case middleName = "middlename"
    }
}

И в завершение, это протоколы:

  • Encodable позволяет вам кодировать из вашего объекта (Person типа) в JSON.
  • Decodable позволяет декодировать из вашего JSON в Person,
  • Codable позволяет вам сделать оба, это смесь Encodable а также Decodable,

Если вам просто нужно идти JSON --> Personзатем с помощью Decodable более чем достаточно

Создать кодируемую структуру, как это

struct GalleryDetails: Codable {
    let id: Int
    let customerID: String
    let title: String
    let description: String
}

используйте этот код

func myAPICall() {
        let url = "http://myApp.abc.de/myApp/public/……"

        let headers = [….]

        let Parameters = [….]

        Alamofire.request(url, method: .post, parameters: Parameters, encoding: URLEncoding.httpBody, headers: headers)

            .responseJSON { (response) in
                if let httpResponse = response.response {

                    if httpResponse.statusCode == 200 {
                        if let result = response.result.value as? [String:Any] {

                            if let customerData = result["customer_data"] as? [[String: Any]] {
                                for acustomer_data in customerData {
                                    do {
                                        let jsonData = try JSONSerialization.data(withJSONObject: aContact, options: .prettyPrinted)
                                        let reqJSONStr = String(data: jsonData, encoding: .utf8)
                                        let data = reqJSONStr?.data(using: .utf8)
                                        let jsonDecoder = JSONDecoder()

                                        let aContact = try jsonDecoder.decode(GalleryDetails.self, from: data!)
                                        self.arrdata.append(aContact)
                                    }
                                    catch {

                                    }
                                }

                            }
                        }
                    }
                }
        }
    }
Другие вопросы по тегам