[英]Convert Array of Dictionary to custom object swift
我有:
let countries : [[String : Any]] = [
[
"name" : "Afghanistan",
"dial_code": "+93",
"code": "AF"
],
[
"name": "Aland Islands",
"dial_code": "+358",
"code": "AX"
],
[
"name": "Albania",
"dial_code": "+355",
"code": "AL"
],
[
"name": "Algeria",
"dial_code": "+213",
"code": "DZ"
]
]
我想將所有這些字典數組添加到我的自定義 object 中,例如
let country:[Country] = countries
我的自定義 object 如下所示:
class Country: NSObject {
let name: String
let dial_code : String
let code: String
init(name: String, dial_code: String, code: String) {
self.name = name
self.dial_code = dial_code
self.code = code
}
}
我知道我需要一個遍歷數組的循環,但我不知道下一步是什么。 有一個例子會很棒。
您應該使您的國家/地區符合Codable
協議,使用JSONSerialization
將您的字典轉換為 JSON 數據,然后使用JSONSerialization
對Data
進行JSONDecoder
,請注意,您可以將其keyDecodingStrategy
屬性設置為convertFromSnakeCase
自動避免需要聲明像dial_Code
這樣的自定義編碼鍵:
struct Country: Codable {
let name: String
let dialCode : String
let code: String
}
do {
let json = try JSONSerialization.data(withJSONObject: countries)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decodedCountries = try decoder.decode([Country].self, from: json)
decodedCountries.forEach{print($0)}
} catch {
print(error)
}
國家(名稱:“阿富汗”,撥號代碼:“+93”,代碼:“AF”)
國家(名稱:“奧蘭群島”,撥號代碼:“+358”,代碼:“AX”)
國家(名稱:“阿爾巴尼亞”,撥號代碼:“+355”,代碼:“AL”)
國家(名稱:“阿爾及利亞”,撥號代碼:“+213”,代碼:“DZ”)
不相關但刪除NSObject
直到需要
這是很簡單的事情,你只需要想一想
像這樣創建對象
var arr = [Country]()
現在循環你的字典數組
for dict in countries {
// Condition required to check for type safety :)
guard let name = dict["name"] as? String,
let dialCode = dict["dial_code"] as? String,
let code = dict["code"] as? String else {
print("Something is not well")
continue
}
let object = Country(name: name, dial_code:dialCode, code:code)
arr.append(object)
}
就是這樣您已將 dict 數組轉換為自定義對象
希望對你有幫助
您可以使用列表的flatMap
方法來生成結果:
countries.flatMap { (v: [String: Any]) -> Country? in
if let name = v["name"] as? String,
let dial = v["dial_code"] as? String,
let code = v["code"] as? String {
return Country(name: name, dial_code: dial, code: code)
} else {
return nil
}
}
一個完整的例子是:
//: Playground - noun: a place where people can play
import UIKit
let countries : [[String : Any]] = [
[
"name" : "Afghanistan",
"dial_code": "+93",
"code": "AF"
],
[
"name": "Aland Islands",
"dial_code": "+358",
"code": "AX"
],
[
"name": "Albania",
"dial_code": "+355",
"code": "AL"
],
[
"name": "Algeria",
"dial_code": "+213",
"code": "DZ"
]
]
class Country: NSObject {
let name: String
let dial_code : String
let code: String
init(name: String, dial_code: String, code: String) {
self.name = name
self.dial_code = dial_code
self.code = code
}
}
let cnt = countries.flatMap { (v: [String: Any]) -> Country? in
if let name = v["name"] as? String, let dial = v["dial_code"] as? String, let code = v["code"] as? String {
return Country(name: name, dial_code: dial, code: code)
} else {
return nil
}
}
print (cnt)
已經有很多答案,但我發現其中大部分都有缺點。 這就是我的建議:
extension Country {
init?(fromDict dict: [String: Any]) {
guard let name = dict["name"] as? String,
let dialCode = dict["dial_code"] as? String,
let code = dict["code"] as? String else {
return nil
}
self.init(name: name, dialCode: dialCode, code: code)
}
}
let countries = countryDictionaries.map { dict -> Country in
if let country = Country(fromDict: dict) { return Country }
else {
preconditionFailure("Tried to convert an invalid dict into a country")
// TODO: handle error appropriately
}
}
如果您只想忽略無效的國家/地區詞典,那就更簡單了:
let countries = countryDictionaries.flatMap(Country.init(fromDict:))
非常簡單明了的解決方案:
Country
使用參數 json [String : Any]
創建自定義初始值設定項。試試這個代碼:
class Country: NSObject {
var name: String = ""
var dial_code: String = ""
var code: String = ""
// Sol: 1
init(json: [String : Any]) {
if let name = json["name"] as? String, let dial_code = json["dial_code"] as? String, let code = json["name"] as? String {
self.name = name
self.dial_code = dial_code
self.code = code
}
}
// or Sol: 2
init(name: String, dial_code: String, code: String) {
self.name = name
self.dial_code = dial_code
self.code = code
}
}
Countries
使用數組元素countries
,並收集同在單獨的數組arrayOfCountries
試試這個代碼:
let countries : [[String : Any]] = [
[
"name" : "Afghanistan",
"dial_code": "+93",
"code": "AF"
],
[
"name": "Aland Islands",
"dial_code": "+358",
"code": "AX"
],
[
"name": "Albania",
"dial_code": "+355",
"code": "AL"
],
[
"name": "Algeria",
"dial_code": "+213",
"code": "DZ"
]
]
var arrayOfCountries = [Country]()
// Sol: 1
for json in countries {
let country = Country(json: json)
print("country name - \(country.name)")
arrayOfCountries.append(country)
}
// Sol: 2
for json in countries {
if let name = json["name"] as? String, let dial_code = json["dial_code"] as? String, let code = json["name"] as? String {
let country = Country(name: name, dial_code: dial_code, code: code)
print("country name - \(country.name)")
arrayOfCountries.append(country)
}
}
使用參數 json [String : Any] 創建自定義國家/地區類
class Country: NSObject {
var name: String?
var dialCode: String?
var code: String?
init(json: [String : Any]) {
self.name = json["name"] as? String
self.dialCode = json["dial_code"] as? String
self.code = json["code"] as? String
}
}
稍后您可以使用將字典映射到國家/地區數組中
let _ = countries.flatMap { Country.init }
這是一個有用的擴展,它從預定義的返回類型推斷類型:
extension Dictionary {
func castToObject<T: Decodable>() -> T? {
let json = try? JSONSerialization.data(withJSONObject: self)
return json == nil ? nil : try? JSONDecoder().decode(T.self, from: json!)
}
}
用法是:
struct Person: Decodable {
let name: String
}
let person: Person? = ["name": "John"].castToObject()
print(person?.name) // Optional("John")
首先你需要初始化一個Country Class的空數組類型
var countryArray = [Country]()
//then you have to loop thru the countries dictionary
//and after casting them adding it to this empty array with class initializer
countries.forEach { (dict) in
countryArray.append(Country(name: dict["name"] as! String, dial_code: dict["dial_code"] as! String, code: dict["code"] as! String))
}
//this is how you reach to properties
countryArray.forEach { (country) in
print(country.name)
}
您可以將字典映射到數組中。 由於字典總是為 key 返回一個可選值(該值不能保證存在),因此您需要一個守衛來確保只有在這種情況下才能繼續。
在這個示例解決方案中,如果任何值不存在,我就會拋出 - 但這真的取決於你來決定。
struct AnError: Error {}
do {
let countryObjects: [Country] = try countries.map {
guard let name = $0["name"] as? String,
let dial_code = $0["dial_code"] as? String,
let code = $0["code"] as? String else {throw AnError()}
return Country(name: name, dial_code: dial_code, code: code)
}
}
catch {
//something went worng - handle the error
}
你可以像這樣使用Array.foreach
countries.forEach{country.append(Country($0))}
並且您可以將Country
init
參數更改為[String: Any]
,或者將$0
為[String: Any]
並從中讀取您的值並將它們發送到init
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.