簡體   English   中英

將字典數組轉換為自定義數組 object swift

[英]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 數據,然后使用JSONSerializationData進行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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM