Использование 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)
}
}
}
}
}
}
Это работает нормально. Но мое беспокойство заключается в следующем...
Я сделал простую структуру. Как я могу использовать
Codable-Decodable
структура вместо этой простой структуры..?При разборе, как я могу использовать
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 {
}
}
}
}
}
}
}
}