<iOS 實(shí)踐>一種實(shí)體轉(zhuǎn)字典的思路

在日常開發(fā)活動(dòng)中, 很多時(shí)候都需要將某個(gè)實(shí)體轉(zhuǎn)換為字典, 而轉(zhuǎn)換字典的方式有千千萬萬種, 這里介紹一種利用 Swift 的反射獲取屬性并轉(zhuǎn)換的方式.

原理就是利用 Mirror 類提供的能力將實(shí)體中所有屬性都遍歷出來, 然后將屬性名作為 key, 屬性值作為 value 存入到字典中.

首先定義一個(gè)協(xié)議, 有了協(xié)議之后可以很方便地為協(xié)議提供默認(rèn)實(shí)現(xiàn), 從而避免對(duì)每個(gè)實(shí)體類型都單獨(dú)寫轉(zhuǎn)換方法:

/// 字典轉(zhuǎn)換協(xié)議
protocol DictionaryConvertible {
    /// 將實(shí)體轉(zhuǎn)換為字典.
    ///
    /// - Returns: 實(shí)體對(duì)應(yīng)的字典
    func toDictionary() -> [String: Any]
}

定義好了這個(gè)協(xié)議, 就可以給這個(gè)協(xié)議提供默認(rèn)實(shí)現(xiàn)了:

extension DictionaryConvertible {
    func toDictionary() -> [String: Any] {
        var dictionary = [String: Any]()
        let mirrorSelf = Mirror(reflecting: self)
        mirrorSelf.children.forEach({ label, value in
            guard let key = label else { return }
            if let array = value as? Array<DictionaryConvertible> {
                dictionary[key] = array.map({ $0.toDictionary() })
            } else if let convertible = value as? DictionaryConvertible {
                dictionary[key] = convertible.toDictionary()
            } else {
                dictionary[key] = value
            }
        })
        return dictionary
    }
}

其中考慮了實(shí)體屬性是如下兩種類型的可能:

  • 屬性是 DictionaryConvertible, 則對(duì)該屬性的值也進(jìn)行字典轉(zhuǎn)換.

  • 屬性是 DictionaryConvertible 數(shù)組, 則將數(shù)組的每個(gè)元素都轉(zhuǎn)換為字典.

完整代碼如下:

protocol DictionaryConvertible {
    /// 將實(shí)體轉(zhuǎn)換為字典.
    ///
    /// - Returns: 實(shí)體對(duì)應(yīng)的字典
    func toDictionary() -> [String: Any]
}

extension DictionaryConvertible {
    func toDictionary() -> [String: Any] {
        var dictionary = [String: Any]()
        let mirrorSelf = Mirror(reflecting: self)
        mirrorSelf.children.forEach({ label, value in
            guard let key = label else { return }
            if let array = value as? Array<DictionaryConvertible> {
                dictionary[key] = array.map({ $0.toDictionary() })
            } else if let convertible = value as? DictionaryConvertible {
                dictionary[key] = convertible.toDictionary()
            } else {
                dictionary[key] = value
            }
        })
        return dictionary
    }
}

在實(shí)際使用時(shí), 假設(shè)有如下實(shí)體類型:

struct MyInnerConsParam: Encodable, DictionaryConvertible {
    let info: String
    let price: Double
}

struct MyConsPostParam: Encodable, DictionaryConvertible {
    let name: String
    let num: Int
    let inner: MyInnerConsParam
}

只要讓實(shí)體遵守 DictionaryConvertible 協(xié)議即可獲取字典轉(zhuǎn)換能力:

let inner = MyInnerConsParam(info: "這個(gè)有信息", price: 33.3)
let param = MyConPostParam(name: "二狗", num: 11, inner: inner)
let dict = param.toDictionary()
print(dict)

打印結(jié)果如下:

["inner": ["info": "這個(gè)有信息", "price": 33.3], "name": "二狗", "num": 11]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容